【XR806开发板试用】通过MQTT实现手机远程实现PWM控灯

news2024/11/6 3:05:22

本文参与极术社区的《基于安谋科技STAR-MC1的XR806开发板试用》活动。

一、例程编译、烧录确认
首先按照全志在线文档平台的点灯教程确保能正常编译、烧录和点灯:https://xr806.docs.aw-ol.com/study/soft_led/
确保例程没问题后,我们再改造例程,实现我们想要的功能

二、代码编写
我们将led工程复制一份改文件夹名为mydemo,目录结构如下

    mydemo
    ├── BUILD.gn
    └── src
    └── main.c

然后BUILD.gn内容增加头文件引用,部分配置如下:

static_library("app_mydemo") {
...
include_dirs += [
      "//kernel/liteos_m/kernel/arch/include",
      "//base/iot_hardware/peripheral/interfaces/kits",

      ".",
      "//utils/native/lite/include",
      "//foundation/communication/wifi_lite/interfaces/wifiservice",
      "//device/xradio/xr806/xr_skylark/project"
   ]
}

接下来是main.c,内容如下:

#include <stdio.h>
#include <string.h>
#include "ohos_init.h"
#include "kernel/os/os.h"

#include "iot_gpio.h"
#include "wifi_device.h"
#include "common/framework/net_ctrl.h"
#include "net/mqtt/MQTTClient-C/MQTTClient.h"
#include "driver/chip/hal_pwm.h"

static OS_Thread_t g_main_thread;
static OS_Thread_t g_mqtt_thread;

#define PWM_OUTPUT_CHL        PWM_GROUP1_CH2
#define PWM_OUTPUT_MODE       PWM_CYCLE_MODE

#define WIFI_DEVICE_CONNECT_AP_SSID "ssid"//这里填你家路由器的SSID
#define WIFI_DEVICE_CONNECT_AP_PSK "pwm"//这里填你家路由器的PWD


#define MQTT_DEMO_CLIENT_ID "12345"
#define MQTT_DEMO_HOST_NAME "broker-cn.emqx.io"//这个是免费调试用的MQTT服务器地址
#define MQTT_DEMO_PORT      "1883"
#define MQTT_DEMO_USERNAME  "12345678"
#define MQTT_DEMO_PASSWORD  "12345678"
#define MQTT_RESP_TOPIC "/to/master/light" //手机发出来的TOPIC
#define MQTT_RECV_TOPIC  "/to/slave/light" //设备发出来的TOPIC
#define MQTT_DEMO_BUF_SIZE (2*1024)

static MQTTPacket_connectData mqtt_demo_connectData = MQTTPacket_connectData_initializer;
static Client mqtt_demo_client;
static Network mqtt_demo_network;
static int max_duty_ratio = 0;

static int mqtt_demo_publish(char *topic, char *msg) ;

static int mqtt_demo_init(void) {
	char *send_buf;
	char *recv_buf;

	mqtt_demo_connectData.clientID.cstring = MQTT_DEMO_CLIENT_ID;
	mqtt_demo_connectData.keepAliveInterval = 30; // 30s
	mqtt_demo_connectData.cleansession = 0;
	mqtt_demo_connectData.MQTTVersion = 4; //Version of MQTT 3.1.1

	send_buf = malloc(MQTT_DEMO_BUF_SIZE);
	if (send_buf == NULL) {
		printf("no memory\n");
		return -1;
	}
	recv_buf = malloc(MQTT_DEMO_BUF_SIZE);
	if (recv_buf == NULL) {
		free(send_buf);
		printf("no memory\n");
		return -1;
	}

	/* init network */
	NewNetwork(&mqtt_demo_network);
	/* init mqtt client object */
	MQTTClient(&mqtt_demo_client, &mqtt_demo_network, 6000,
	           (unsigned char *)send_buf, MQTT_DEMO_BUF_SIZE,
	           (unsigned char *)recv_buf, MQTT_DEMO_BUF_SIZE);

	/* set username and password */
	mqtt_demo_connectData.username.cstring = MQTT_DEMO_USERNAME;
	mqtt_demo_connectData.password.cstring = MQTT_DEMO_PASSWORD;
	return 0;
}

static int mqtt_demo_connect(char *host_name, char *host_port) {
	int ret = -1;

	ret = ConnectNetwork(&mqtt_demo_network, host_name, atoi(host_port));
	if (ret != 0) {
		printf("mqtt connect faild, ret:%d, host:%s, port:%s\n", ret, host_name, host_port);
		goto exit;
	}

	ret = MQTTConnect(&mqtt_demo_client, &mqtt_demo_connectData);
	if (ret != 0) {
		printf("mqtt connect faild, ret:%d\n", ret);
		mqtt_demo_network.disconnect(&mqtt_demo_network);
		goto exit;
	}
	printf("mqtt connected\n");
exit:
	return ret;
}

static void mqtt_demo_msg_cb(MessageData *data) {
	printf("get a message, topic: %.*s, msg: %.*s\n", data->topicName->lenstring.len,
	       data->topicName->lenstring.data, data->message->payloadlen,
	       (char *)data->message->payload);
	if(!strncmp(data->topicName->lenstring.data, "/to/slave/light", 15) && data->message->payloadlen) {
		char *payload = data->message->payload;
		char str[8] = "";
		int max_len = data->message->payloadlen > 3 ? 3 : data->message->payloadlen;
		strncpy(str, payload, max_len);
		int duty = atoi(str);
		HAL_Status status = HAL_PWM_ChSetDutyRatio(PWM_OUTPUT_CHL, duty * max_duty_ratio / 100);
		if (status != HAL_OK)
			printf("%s(): %d, PWM set duty ratio error\n", __func__, __LINE__);
		
		if(duty) {
			mqtt_demo_publish(MQTT_RESP_TOPIC, "light on");
		} else {
			mqtt_demo_publish(MQTT_RESP_TOPIC, "light off");
		}
	} 
}

static int mqtt_demo_subscribe(char *topic) {
	int ret = -1;
	if (mqtt_demo_client.isconnected) {
		ret = MQTTSubscribe(&mqtt_demo_client, topic, 0, mqtt_demo_msg_cb);
		if (ret != 0)
			printf("mqtt subscribe faild ret:%d\n", ret);
	}
	return ret;
}

static int mqtt_demo_unsubscribe(char *topic) {
	int ret = -1;
	if (mqtt_demo_client.isconnected) {
		ret = MQTTUnsubscribe(&mqtt_demo_client, topic);
		if (ret != 0)
			printf("mqtt unsubscribe faild, ret:%d\n", ret);
	}
	return ret;
}

static int mqtt_demo_publish(char *topic, char *msg) {
	int ret = -1;

	MQTTMessage message;
	memset(&message, 0, sizeof(message));
	message.qos = 0;
	message.retained = 0; /* disable retain the message in server */
	message.payload = msg;
	message.payloadlen = strlen(msg);
	ret = MQTTPublish(&mqtt_demo_client, topic, &message);
	if (ret != 0)
		printf("mqtt publish faild, ret:%d\n", ret);
	return ret;
}

static int mqtt_demo_disconnect(void) {
	int ret = -1;

	if (mqtt_demo_client.isconnected) {
		ret = MQTTDisconnect(&mqtt_demo_client);
		if (ret != 0)
			printf("mqtt disconnect fail, ret:%d\n", ret);
		mqtt_demo_network.disconnect(&mqtt_demo_network);
	}
	return ret;
}

static void mqtt_demo_deinit(void) {
	if (mqtt_demo_client.buf) {
		free(mqtt_demo_client.buf);
		mqtt_demo_client.buf = NULL;
	}
	if (mqtt_demo_client.readbuf) {
		free(mqtt_demo_client.readbuf);
		mqtt_demo_client.readbuf = NULL;
	}
}

static void mqtt_task(void *arg)   {
	int ret;
	int reconnect_times = 0;

	mqtt_demo_init();

	ret = mqtt_demo_connect(MQTT_DEMO_HOST_NAME, MQTT_DEMO_PORT);
	if (ret != 0)
		goto exit;

	ret = mqtt_demo_subscribe(MQTT_RECV_TOPIC);
	if (ret != 0)
		goto exit;

	mqtt_demo_publish(MQTT_RESP_TOPIC, "light ready");

	while (1) {
		ret = MQTTYield(&mqtt_demo_client, 300);
		if (ret != 0) {
			printf("mqtt yield err, ret:%d\n", ret);
reconnect:
			printf("mqtt reconnect\n");
			mqtt_demo_disconnect();
			ret = mqtt_demo_connect(MQTT_DEMO_HOST_NAME, MQTT_DEMO_PORT);
			if (ret != 0) {
				reconnect_times++;
				if (reconnect_times > 5)
					goto exit;
				OS_MSleep(5000); //5s
				goto reconnect;
			}
		}
	}

exit:
	mqtt_demo_unsubscribe(MQTT_RECV_TOPIC);
	mqtt_demo_disconnect();
	mqtt_demo_deinit();
	OS_ThreadDelete(&g_mqtt_thread);
}

static void net_cb(uint32_t event, uint32_t data, void *arg) {
	uint16_t type = EVENT_SUBTYPE(event);
	switch (type) {
	case NET_CTRL_MSG_NETWORK_UP:
		printf("NET_CTRL_MSG_NETWORK_UP\n");
		if (!OS_ThreadIsValid(&g_mqtt_thread)) {
			OS_ThreadCreate(&g_mqtt_thread, "connect_to_server_task",
			                    mqtt_task, (void *)NULL,  OS_THREAD_PRIO_APP, (8 * 1024));
		}
		break;
	case NET_CTRL_MSG_NETWORK_DOWN:
		break;
	default:
		break;
	}
}

static void MainThread(void *arg)   {
	printf("MainThread start\r\n");
	HAL_Status status = HAL_ERROR;
	PWM_ClkParam clk_param;
	PWM_ChInitParam ch_param;

	clk_param.clk = PWM_CLK_HOSC;
	clk_param.div = PWM_SRC_CLK_DIV_1;

	status = HAL_PWM_GroupClkCfg(PWM_OUTPUT_CHL, &clk_param);
	if (status != HAL_OK)
		printf("%s(): %d, PWM group clk config error\n", __func__, __LINE__);

	ch_param.hz = 1000;
	ch_param.mode = PWM_OUTPUT_MODE;
	ch_param.polarity = PWM_HIGHLEVE;
	max_duty_ratio = HAL_PWM_ChInit(PWM_OUTPUT_CHL, &ch_param);
	if (max_duty_ratio == -1)
		printf("%s(): %d, PWM ch init error\n", __func__, __LINE__);

	printf("max_duty_ratio=%d\n", max_duty_ratio);
	status = HAL_PWM_ChSetDutyRatio(PWM_OUTPUT_CHL, 0);
	if (status != HAL_OK)
		printf("%s(): %d, PWM set duty ratio error\n", __func__, __LINE__);

	status = HAL_PWM_EnableCh(PWM_OUTPUT_CHL, PWM_OUTPUT_MODE, 1);
	if (status != HAL_OK)
		printf("%s(): %d, PWM ch enable error\n", __func__, __LINE__);

	if (WIFI_SUCCESS != EnableWifi()) {
		printf("Error: EnableWifi fail\n");
		return;
	}

	OS_Sleep(1);

	if (WIFI_SUCCESS != Scan()) {
		printf("Error: Scan fail.\n");
		return;
	}

	OS_Sleep(3);//这里为了方便用延时,实际用回调更好,否则3秒可能不够

	const char ssid_want_connect[] = WIFI_DEVICE_CONNECT_AP_SSID;
	const char psk[] = WIFI_DEVICE_CONNECT_AP_PSK;
	WifiScanInfo scan_results[30];
	unsigned int scan_num = 30;

	if (WIFI_SUCCESS != GetScanInfoList(scan_results, &scan_num)) {
		printf("Error: GetScanInfoList fail.\n");
		return;
	}

	WifiDeviceConfig config = { 0 };
	int netId = 0;

	int i;
	for (i = 0; i < scan_num; i++) {
		printf("ssid: %s    ", scan_results[i].ssid);
		printf("securityType: %d\n", scan_results[i].securityType);
		if (0 == strcmp(scan_results[i].ssid, ssid_want_connect)) {
			memcpy(config.ssid, scan_results[i].ssid,
			       WIFI_MAX_SSID_LEN);
			memcpy(config.bssid, scan_results[i].bssid,
			       WIFI_MAC_LEN);
			strcpy(config.preSharedKey, psk);
			config.securityType = scan_results[i].securityType;
			config.wapiPskType = WIFI_PSK_TYPE_ASCII;
			config.freq = scan_results[i].frequency;
			break;
		}
	}

	if (i >= scan_num) {
		printf("Error: No found ssid in scan_results\n");
		return;
	}

	if (WIFI_SUCCESS != AddDeviceConfig(&config, &netId)) {
		printf("Error: AddDeviceConfig Fail\n");
		return;
	}
	printf("Config Success\n");

	if (WIFI_SUCCESS != ConnectTo(netId)) {
		printf("Error: ConnectTo Fail\n");
		return;
	}
	
	observer_base *net_ob;
	net_ob = sys_callback_observer_create(CTRL_MSG_TYPE_NETWORK, NET_CTRL_MSG_ALL, net_cb, NULL);
	if (net_ob == NULL)
		return;

	if (sys_ctrl_attach(net_ob) != 0)
		return;

	while (1) {
		OS_MSleep(500);
	}
}

void LEDMain(void) {
	if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL, OS_THREAD_PRIO_APP, 4 * 1024) != OS_OK) {
		printf("[ERR] Create MainThread Failed\n");
	}
}

SYS_RUN(LEDMain);

三、配置上层的BUILD.gn,并编译
部分内容如下:

group("ohosdemo") {
    deps = [
        #"hello_demo:app_hello",
        #"iot_peripheral:app_peripheral",
        #"wlan_demo:app_WlanTest",
        "mydemo:app_mydemo",
    ]
}

然后执行hb build -f,编译成功(若编译失败见论坛有解决方案)
然后烧录到开发板上

四、运行实例
烧录完成后,开发板重新上电,输出如下日志

====================================================================
	Hello! OpenHarmony!
	System tag : OpenHarmony 1.1.2_LTS
====================================================================
	
use default flash chip mJedec 0x0
[FD I]: mode: 0x10, freq: 96000000Hz, drv: 0
[FD I]: jedec: 0x0, suspend_support: 1
mode select:e

wlan information ===================================================
firmware:
    version : R0-XR_C07.08.52.65_02.84 May 27 2021 11:41:33-Y02.84 
    buffer  : 8
driver:
    version : XR_V02.05
mac address:
    in use        : 1c:98:c9:bc:50:01
    in use        : 1c:98:c9:bc:50:02
====================================================================

wlan mode:a
[VFS INF] LittleFS mount success.

platform information ===============================================
XR806 SDK v1.2.0  Dec 13 2021 13:06:05

heap space [0x2238d0, 0x24bc00), size 164656

cpu  clock 160000000 Hz
HF   clock  40000000 Hz

sdk option:
    XIP           : enable
    INT LF OSC    : enable
    SIP flash     : enable

mac address:
    efuse         : 80:74:84:21:38:8e
    in use        : 1c:98:c9:bc:50:01
====================================================================

hiview init success.MainThread start

max_duty_ratio=40000


console init success

[net INF] no need to switch wlan mode 0
[net INF] msg <wlan scan success>
ssid: TP-LINK_A668    securityType: 2
Config Success
[net INF] no need to switch wlan mode 0
en1: Trying to associate with a4:c7:4b:71:f9:84 (SSID='XXXXXX' freq=2462 MHz)
en1: Associated with a4:c7:4b:71:f9:84
en1: WPA: Key negotiation completed with a4:c7:4b:71:f9:84 [PTK=CCMP GTK=CCMP]
en1: CTRL-EVENT-CONNECTED - Connection to a4:c7:4b:71:f9:84 completed [id=0 id_str=]
[net INF] msg <wlan connected>
[net INF] netif is link up
[net INF] start DHCP...
[net INF] IPv6 addr state change: 0x0 --> 0x1
[net INF] msg <>
[net INF] netif (IPv4) is up
[net INF] address: 192.168.3.48
[net INF] gateway: 192.168.3.1
[net INF] netmask: 255.255.255.0
[net INF] msg <network IPv6 state>
NET_CTRL_MSG_NETWORK_UP
WAR drop=1117, fctl=0x00d0.
mqtt connected
get a message, topic: /to/slave/light, msg: 0

可以看到,开发板成功连接路由器,并接入了MQTT服务器

五、手机测试
本人的手机是Iphone,也不会手机APP开发,于是我们下载了一个叫MQTTTool的第三方APP验证点灯,其界面如下:
在这里插入图片描述

Host和Port填对,由于是免费开放的MQTT服务器,其他参数任意,设置好以后点Connect即可连接上MQTT服务器。然后底部切换至Subscribe栏,订阅主题:
在这里插入图片描述

若手机比设备先连接服务器并订阅相关主题,那么你会在订阅栏收到topic为/to/master/light的消息:light ready,这是因为设备连上服务器就会发布该topic。
接下来是发布主题,我们往/to/slave/light主题发送一个0~100的数字,就会让设备以这个数字为占空比控制LED灯亮灭,如0表示灭灯,50表示50%的占空比驱动LED灯,100表示100%的占空比驱动LED灯。同时设备收到LED控制指令后,若占空比不为0,则发送消息light on,否则发送消息light off
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

部分日志如下:

WAR drop=1117, fctl=0x00d0.
mqtt connected
get a message, topic: /to/slave/light, msg: 0
[net INF] IPv6 addr state change: 0x0 --> 0x1
[net INF] msg <>
get a message, topic: /to/slave/light, msg: 100
get a message, topic: /to/slave/light, msg: 100
get a message, topic: /to/slave/light, msg: 50

以上就是一个手机远程给LED进行PWM调光的应用实例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1406886.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java入门高频考查基础知识5(扎实技术基础应变一切变化-45题4.2万字参考答案)

技术变革裁员影响的因素&#xff1a; 自动化替代简单重复性工作&#xff1a;随着技术的发展&#xff0c;一些简单、重复性的编码任务可能被自动化工具或者机器学习算法取代。这可能导致一些岗位的需求减少或者消失&#xff0c;从而可能导致部分人员裁员。 技能更新要求&#x…

怎么移除WordPress后台工具栏“新建”菜单?如何添加“新建文章”菜单?

默认情况下&#xff0c;WordPress后台顶部管理工具栏有左侧有一个“新建”菜单&#xff0c;而且还有下拉菜单文章、媒体、链接、页面和用户等&#xff0c;不过我们平时用得最多的就是“新建文章”&#xff0c;虽然可以直接点击“新建”&#xff0c;或点击“新建 – 文章”&…

Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))

目录 AOP概念AOP底层原理AOP(JDK动态代理)使用 JDK 动态代理&#xff0c;使用 Proxy 类里面的方法创建代理对象**编写** **JDK** 动态代理代码 AOP(术语)AOP操作&#xff08;准备工作&#xff09;**AOP** **操作&#xff08;**AspectJ注解)**AOP** **操作&#xff08;**AspectJ…

c++ 包管理工具vcpkg

微软包管理工具 一、下载 git clone https://github.com/microsoft/vcpkg二、初始化 ./vcpkg/bootstrap-vcpkg.sh三、查看帮助文档 ./vcpkg/vcpkg help四、安装包 vcpkg/vcpkg install fmt五、查看安装包 vcpkg/vcpkg list输出 包实际安装路径 ./vcpkg/packages/fmt_x…

LoadRunner从零开始之走近LoadRunner

3.1 LoadRunner 的运行原理 安装LoadRunner 后&#xff0c;在菜单“开始” 一“MercuryLoadRunner” 中&#xff0c;你会看 到这样一组程序&#xff0c;如图 3-1 所示。 • 其中Applications 下面的Analysis、Controller 和Virtual User Generator 是我们 做性能测试最常用的…

大学生求职遇到在线测评 需要结合实际做吗

每年毕业季&#xff0c;都有大量的大学生求职&#xff0c;企业在这个时候往往能够收到很多的求职简历&#xff0c;尤其是一些比较好的岗位&#xff0c;原本只是想要招收10个人&#xff0c;但是结果光是简历就收到上千个简历&#xff0c;一个个面试不实际&#xff0c;浪费时间和…

猫用空气净化器哪些好?五款宠物空气净化推荐!

如今&#xff0c;养宠物的家庭越来越多了&#xff01;家里因此变得更加温馨&#xff0c;但同时也会带来一些问题&#xff0c;比如异味和空气中的毛发可能会对健康造成困扰。 为了避免家中弥漫着异味&#xff0c;特别是来自宠物便便的味道&#xff0c;一款能够处理家里异味的宠…

数字证书和数字证书认证机构和数字根证书,CA,RCA

文章目录 一、 数字证书1、什么是数字证书2、数字证书干什么的3、风险 二、数字证书认证机构&#xff08;Certificate Authority&#xff0c;缩写为CA&#xff09;参考文章 一、 数字证书 维基百科 公开密钥认证&#xff08;英语&#xff1a;Public key certificate&#xff…

Unity Text超框 文字滚动循环显示

Unity Text超框 文字滚动循环显示 //container Text using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.UI;public class AutoScrollText : MonoBehaviour {private Text[] _texts new Text[…

项目难点和优化

难点: 对于同一个位置百度地图定位的经纬度和腾讯地图定位的经纬度不一样&#xff1f; 解决&#xff1a;由于两者所用的算法不同&#xff0c;计算出来的经纬度也是不一样的&#xff0c;将百度地图的经纬度转换成腾讯地图的经纬度/腾讯的经纬度转化百度的经纬度 export functi…

【超简版,代码可用!】【0基础Python爬虫入门——下载歌曲/视频】

安装第三方模块— requests 完成图片操作后输入&#xff1a;pip install requests 科普&#xff1a; get:公开数据 post:加密 &#xff0c;个人信息 进入某音乐网页&#xff0c;打开开发者工具F12 选择网络&#xff0c;再选择—>媒体——>获取URL【先完成刷新页面】 科…

环保投入超20亿,齐鲁制药集团争做绿色制药标杆

近期&#xff0c;由人民日报社指导、人民网主办的2023人民企业社会责任荣誉盛典暨第十八届人民企业社会责任奖颁奖活动在京举行&#xff0c;齐鲁制药集团荣获“人民企业社会责任奖绿色发展奖”。多年来&#xff0c;齐鲁制药深入践行“绿水青山就是金山银山”理念&#xff0c;积…

【Linux】Linux进程间通信

Linux进程间通信 一、进程间通信介绍1、概念2、进程间通信目的3、进程间通信的本质4、进程间通信分类 二、管道1、什么是管道2、匿名管道&#xff08;1&#xff09;匿名管道原理&#xff08;2&#xff09;pipe函数&#xff08;3&#xff09;匿名管道的使用步骤i、父进程调用pip…

SUSE Linux 12 SP5 安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

idea中debug Go程序报错error layer=debugger could not patch runtime.mallogc

一、问题场景 在idea中配置了Go编程环境&#xff0c;可以运行Go程序&#xff0c;但是无法debug&#xff0c;报错error layerdebugger could not patch runtime.mallogc: no type entry found, use ‘types’ for a list of valid types 二、解决方案 这是由于idea中使用的d…

定向减免!函数计算让 ETL 数据加工更简单

业内较为常见的高频短时 ETL 数据加工场景&#xff0c;即频率高时延短&#xff0c;一般费用大头均在函数调用次数上&#xff0c;推荐方案一般为攒批处理&#xff0c;高额的计算成本往往令用户感到头疼&#xff0c;函数计算推出定向减免方案&#xff0c;让 ETL数据加工更简单、更…

一篇文章带你搞懂非关系型数据库MongoDB

目录 一、引言 二、核心概念 三、使用场景 四、最佳实践 五、总结 一、引言 随着互联网技术的快速发展&#xff0c;大数据和云计算的普及&#xff0c;传统的关系型数据库在处理海量数据和高并发请求时逐渐显得力不从心。为了满足这些新的需求&#xff0c;非关系型数据库应…

MySQL45道练习题

作业需要数据表SQL语句已给 1. 查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数 select * from Student RIGHT JOIN (select t1.SId, class1, class2 from(select SId, score as class1 from sc where sc.CId 01)as t1, (select SId, score as …

鸿蒙 HarmonyOS ArkTS 点击事件,获取被点击对象的的位置

EntryComponentstruct Page {State screenX:number 0State screenY:number 0State X:number 0State Y:number 0State timestamp:number 0build () {Row () {Column(){Text(应用窗口左上角的X坐标: this.screenX).fontColor(Color.White).margin({bottom:20})Text(应用窗口…

Python教程91:海龟画图turtle画(三角形、正方形、五边形、六边形、圆、同心圆、边切圆,五角星,椭圆)

---------------turtle源码集合--------------- Python教程91&#xff1a;关于海龟画图&#xff0c;Turtle模块需要学习的知识点 Python源码49&#xff1a;海龟画图turtle画美国旗 Python教程48&#xff1a;海龟画图turtle画太极八卦阵 Python源码47&#xff1a;海龟画图tu…