【XR806开发板试用】XR806在U8G2上增加MQTT+JSON控制

news2024/11/15 9:14:09

一、前言

  1. U8G2移植参见之前写的文章 https://aijishu.com/a/1060000000292472
  2. 本次增加MQTT+JSON是站在大佬的肩膀上,参见 https://aijishu.com/a/1060000000284320
  3. CJSON的使用,参见 https://blog.csdn.net/fengxinlinux/article/details/53121287

二、成果

  1. 目录结构:在这里插入图片描述

  2. test_mqtt.c 基本上照搬大佬的代码,内容如下:

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

#include "wifi_device.h"
#include "common/framework/net_ctrl.h"
#include "net/mqtt/MQTTClient-C/MQTTClient.h"
#include "cjson/cJSON.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 "TP-LINK_EEF3" /* 这里填你家路由器的SSID */
#define WIFI_DEVICE_CONNECT_AP_PSK "13677668125"  /* 这里填你家路由器的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/weixin/display" /* 设备发出来的TOPIC */
#define MQTT_RECV_TOPIC  "/to/xr806/display" /* 手机发出来的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) ;

void test_set_str(uint8_t *pstr, uint8_t plen);

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, MQTT_RECV_TOPIC, 15) && data->message->payloadlen)
	{
        char *payload = data->message->payload;

        cJSON *root;
        cJSON *json_display;
        root = cJSON_Parse(payload);
        if (root)
        {
            json_display = cJSON_GetObjectItem(root, "display");

            if (json_display)
            {
                printf("mqtt display!\r\n");
                test_set_str(json_display->valuestring, strlen(json_display->valuestring));

                cJSON * usr;

                usr  = cJSON_CreateObject();   /* 创建根数据对象 */
                cJSON_AddStringToObject(usr, "msg", "success");  /* 加入键值,加字符串 */

                char *out = cJSON_Print(usr);   //将json形式打印成正常字符串形 */
                printf("%s\n", out);

                mqtt_demo_publish(MQTT_RESP_TOPIC, out);

                /* 释放内存 */
                cJSON_Delete(usr);
            }

            cJSON_Delete(root);  /* 释放内存 */
        }
    }
}

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, "mqtt 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("Mqtt start\r\n");

    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");
    }
}
  1. main.c内容如下:
#include <stdio.h>
#include "ohos_init.h"
#include "kernel/os/os.h"
#include "test_i2c.h"
#include  "test_mqtt.h"
#include "iot_i2c.h"
#include "oled.h"
#include "u8g2.h"

static OS_Thread_t g_main_thread;
static uint8_t status=  0;
static uint8_t str[8] = {0};

uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8g2_gpio_and_delay_stm32(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr);
void delay_ms(uint32_t ms);

void test_set_str(uint8_t *pstr, uint8_t plen)
{
	uint8_t vi;

	status = 1;

	for (vi = 0; vi < plen; vi++)
	{
		str[vi] = pstr[vi];
	}
	str[vi] = 0;
}

static void MainThread(void *arg)
{
	u8g2_t u8g2;

	IotI2CTest();

	u8g2_Setup_sh1106_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8g2_gpio_and_delay_stm32);
	//u8g2_InitDisplay(&u8g2);
	u8g2_SetPowerSave(&u8g2, 0);
	u8g2_ClearDisplay(&u8g2);
	u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_chinese1);
	u8g2_DrawCircle(&u8g2, 55, 30,  5,  U8G2_DRAW_ALL);
	u8g2_DrawCircle(&u8g2, 65, 30,  5,  U8G2_DRAW_ALL);
	u8g2_DrawCircle(&u8g2, 75, 30,  5,  U8G2_DRAW_ALL);
	u8g2_DrawUTF8(&u8g2, 20, 50, "你好, XR806!");
	u8g2_SendBuffer(&u8g2);

	while (1)
	{
		if (status == 1)
		{
			status = 0;
			printf("u8g2 display:%s\r\n", str);
			memset(u8g2.tile_buf_ptr, 0, 128*24/8);
			u8g2_DrawUTF8(&u8g2, 20, 20, str);
			u8g2_SendBuffer(&u8g2);
		}

		printf("hello world!\n");
		LOS_Msleep(1000);
	}
}

uint8_t u8g2_gpio_and_delay_stm32(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
	switch(msg)
	{
	case U8X8_MSG_GPIO_AND_DELAY_INIT:
	break;

	case U8X8_MSG_DELAY_MILLI:
		delay_ms(arg_int);
	break;

	default:
		return 0;
	}
	return 1;
}

uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
	static uint8_t buffer[131];		/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
	static uint8_t buf_idx;
	uint8_t *data;

	switch(msg)
	{
	case U8X8_MSG_BYTE_SEND:
		data = (uint8_t *)arg_ptr;
		while( arg_int > 0 )
		{
		buffer[buf_idx++] = *data;
		data++;
		arg_int--;
		}
	break;

	case U8X8_MSG_BYTE_INIT:
		/* add your custom code to init i2c subsystem */
	break;

	case U8X8_MSG_BYTE_START_TRANSFER:
		buf_idx = 0;
	break;

	case U8X8_MSG_BYTE_END_TRANSFER:
		if (buf_idx != 132)
		{
			for (uint8_t i = 0; i < buf_idx; i++)
			{
				OLED_WR_Byte(buffer[i], OLED_CMD);
			}
		}
		else
		{
			for (uint8_t i = 1; i < 4; i++)
			{
				OLED_WR_Byte(buffer[i], OLED_CMD);
			}

			for (uint8_t i = 4; i < buf_idx; i++)
			{
				OLED_WR_Byte(buffer[i], OLED_DATA);
			}
		}
	break;

	default:
		return 0;
	}
	return 1;
}

void delay_ms(uint32_t ms)
{
	uint16_t i,  j;

	for (i = 0; i < ms; i++)
	{
		for (j = 0; j < 10; j++)
		{
			__asm("nop");
		}
	}
}

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

	LEDMain();
}

SYS_RUN(HelloTestMain);
  1. 这里说明一个很奇怪的现象,u8g2_t u8g2;这个变量我改为全局静态变量后,LCD显示内容不对,会出现硬件错误并重启MCU,所以我把u8g2部分代码移动到main.c,通过全局的标志来刷新显示,这一点有待完善,应该使用系统队列来完成此操作。
  2. **效果展示,不知道怎么把图片旋转,知道的留言告诉我,谢谢。在这里插入图片描述

在这里插入图片描述

三、结束语

文章只是初次尝试,实际项目还需要很多的优化,不过使用这个芯片开发感觉还是很迅速,并且有大佬在前方引路还是很奈斯的。

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

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

相关文章

Hive进阶(2)----HDFS写入数据流程(赋图助君理解)

HDFS写入数据流程 一、写入流程 1、 Client向NameNode发起RPC请求&#xff0c;来确定请求文件block所在的位置&#xff1b; 2、 NameNode会视情况返回文件的部分或者全部block列表&#xff0c;对于每个block&#xff0c;NameNode都会返回含有该block副本的DataNode地址&…

如何部署npm私有仓库以及在项目中如何使用

如何部署npm私有仓库以及在项目中如何使用 为什么要部署npm私有仓库&#xff1f; 安全性&#xff1a;私有仓库允许团队存放内部研发的、不宜公开发布的代码包&#xff0c;只对特定用户或者团队可见和可用&#xff0c;从而保护公司的知识产权和商业秘密。模块的复用性&#xf…

友元,const成员,static成员变量,static成员函数

友元&#xff1a; friend关键字: 1.友元函数&#xff1a; 语法&#xff1a; friend在类中修饰一个函数。 那么这个函数定义到全局时仍可以访问该类的私有成员的。 (定义时不需要用friend&#xff0c;而是需要在全局定义前&#xff0c;在要使用的成员的类里进行声明&#xff…

备战面试K8S

备战面试&&K8S Kubernetes关于DockerDocker的优缺点分析 WebAssemblyWebAssembly与Container比较 CtrCrictlCtr和CriCtl的区别 Pod生命周期PodConditions容器状态Pod容器组成生命周期的流程 Kubelet EFK日志采集工具的优缺点 Kubernetes 容器运行接口 Container Runti…

Tensorflow小技巧01:检测本地Tensorflow的版本

前言&#xff1a; 以Pycharm为例&#xff0c;Windwos10系统&#xff0c;检测本地环境的Tensorflow的版本&#xff1a; 1 打开Pycharm窗口 2 在窗口中输入&#xff1a; pythonPython 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win…

ChatGPT与Python-GEE融合,遥感云大数据分析、管理与可视化

掌握Earth Engine的实际应用能力&#xff0c;以Python为基础&#xff0c;结合实例讲解平台搭建、影像数据分析、经典应用案例、本地与云端数据管理&#xff0c;以及云端数据论文出版级可视化等技能。 为提高教学质量&#xff0c;将融入ChatGPT 4、Claude Opus、Gemini、文心一…

Centos7.9 脚本一键部署nextcloud,配置Nginx代理Https。

目录 一键安装nextcloud 出现错误TypeError Cannot read properties of undefined (reading ‘writeText‘) 生成自签名SSL证书 编辑Nginx配置文件 启动Nginx 一键安装nextcloud 本脚本参考文章&#xff0c;本文较长建议先看完在操作&#xff01;&#xff01;&#xff01;…

效率工具:企业微信机器人完成脚本工作-异常监控(sql篇)

效率工具&#xff1a;定时完成脚本工作&#xff08;sql篇&#xff09; 背景&#xff1a;elon在公司需要人工查看某些数据是否异常&#xff0c;并发送到指定企业微信群中。 处理步骤&#xff1a; 工具&#xff1a;企业微信中有机器人 可以指定webhook地址嵌入到脚本中&#xf…

C#语法知识之条件分支语句

4、条件分支语句 目录 4、条件分支语句1、条件分支语句 if1、作用2、if语句3、if...else语句4、if...else if...else语句思考1 只需要0~9数字思考2 语句块 2、条件分支语句 switch1、作用2、基本语法3、default可省略4、自定义常量5、贯穿 1、条件分支语句 if 1、作用 //让顺…

Hive进阶(3)----Checkpoint机制(赋图助君理解)

Checkpoint机制 一、Checkpoint机制概念 本机制可以参考《Hadoop权威指南》第十一章&#xff1a; fsimage文件其实是Hadoop文件系统元数据的一个永久性的检查点&#xff0c;其中包含Hadoop文件系统中的所有目录和文件idnode的序列化信息&#xff1b;fsimage包含Hadoop文件系统…

SpringBoot(一)【入门】

前言 1、SpringBoot 快速入门 1.1、SpringBoot 简介 SpringBoot 是用来简化 Spring 应用的初始搭建以及开发过程 首先我们回顾一下 SpringMVC 项目的开发过程&#xff1a; 导入依赖&#xff08;javax.servlet-api 和 spring-webmvc&#xff09;Servlet 容器配置类&#xff…

Pytest精通指南(14)Parametrize之indirect(间接参数)

文章目录 官方概念概念分析官方示例示例分析验证indirect为True但不指定fixture验证indirect为True但不存在fixture 官方概念 概念分析 在pytest的pytest.mark.parametrize装饰器中&#xff0c;indirect参数用于指示是否应该从fixtures中解析参数值&#xff0c;而不是直接使用提…

爆炸之linux-nacos2.0系列集群安装部署

一、环境配置 1、新建磁盘分区 fdisk /dev/vdb 2、创建文件系统 mkfs.xfs /dev/vdb13、创建挂载点&#xff1a; 在 / 目录下创建一个新的目录作为挂载点。/afc 目录 mkdir /afc4、挂载磁盘&#xff1a; 使用 mount 命令将磁盘挂载到新创建的目录。 mount /dev/vdb /afc5、…

Yoshua Bengio独家专访:我不想把大模型未来押注在Scaling Law上,AGI路上要“注意安全”...

导读 漫长的30年间&#xff0c;数度从主流方向的超然出走&#xff0c;是Bengio的制胜秘诀。这种不盲从主流的风格体现在他研究生涯的方方面面。 90年代末期&#xff0c;神经网络被打入冷宫&#xff0c;Bengio的论文多次遭拒&#xff0c;连学生们也开始担心&#xff0c;和他一起…

Vue之v-on事件修饰符的含义及使用

背景&#xff1a;Vue 拆封了一个组件&#xff0c;在组件里面会使用一个方法来改变父组件传过来的值&#xff0c; 但是在子组件里面操作父组件的数据变更&#xff0c;实在比较麻烦&#xff08;因为单向数据流&#xff09;&#xff0c; So 能不能直接在组件上面绑定事件方法呢&…

springSecurity-记住我(Remember me)

一.记住我概述 Remember me(记住我)记住我&#xff0c;当用户发起登录勾选了记住我&#xff0c;在一定的时间内再次登录就不用输入用户名和密码了&#xff0c;即使浏览器退出重新打开也是如此。 二.流程分析 在SpringSecurity中提供RememberMeAuthenticationFilter过滤器来实…

实时动作检测 | 基于Pytorch+YOLOv5+SlowFast实现的视频流实时动作检测算法_支持多目标的跟踪检测

项目应用场景 面向视频流场景的多目标实时动作检测&#xff0c;项目使用 Pytorch YOLOv5 SlowFast 算法实现。 项目效果 项目细节 > 具体参见项目 README.md (1) 创建 Python 开发环境 conda create -n {your_env_name} python3.7.11 conda activate {your_env_name} (2…

npm镜像源的查看和切换

前言 原域名https://registry.npm.taobao.org/ 原来的淘宝镜像已经不行了,当npm去taobao时,会出现一个证书过期的提示. 下面的是最新的地址: 切换到淘宝镜像(最新的地址) #最新地址 淘宝 NPM 镜像站喊你切换新域名啦! npm config set registry https://registry.npmmirror.com…

00_Linux

文章目录 LinuxLinux操作系统的组成Linux的文件系统Linux操作系统中的文件类型Linux操作系统的组织结构 Linux vs WindowsNAT vs 桥接模式 vs 仅主机Linux Shell命令Linux⽂件与⽬录管理相关指令目录文件普通文件文本编辑 用户管理添加用户删除用户用户组管理 文件权限管理权限…

视频教程下载:用ChatGPT快速提升股票投资能力

学完此视频后可以获得&#xff1a; 学习如何使用人工智能/Chatgpt进行基础/快速/高级财务与研究分析 学习如何使用人工智能/Chatgpt对任何公司进行定性投资研究 学习如何使用人工智能/Chatgpt对任何公司进行定量投资研究 学习如何使用人工智能/Chatgpt创建、预测和分析财务…