发新帖本帖赏金 150.00元(功能说明)我要提问
返回列表
打印
[RISC-V MCU 应用开发]

基于CH32V307和北斗的场面设备监视

[复制链接]
4927|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
51xlf|  楼主 | 2023-1-1 10:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 51xlf 于 2023-1-5 15:03 编辑

#申请原创#      @21小跑堂

该系统使用CH32V307和模块GPS北斗双模定位ATGM336H,通过MQTT协议将定位等相关的数据发给到服务器,并根据前端设备规划监控围栏判断设备是否闯入,并通知相关管理人员,推送相关告警到终端设备,设备接收到命令的时候,对车辆设备进行告警提示,该系统能够为用户提供全面的机场场面活动态势显示;对机场场面活动态势进行自动监控和告警,为系统用户提供告警提示。设备自带有温湿度、MPU6050等设备,可以实现实时监视场面温湿度数据和场面设备的加速度等相关,为场面是否存在结冰条件和事故调查提供依据。设备还预留了CH9141与其他终端设备进行交互。
硬件电路1、整体设计

2、实物图

终端设备

服务器前端

3 硬件电路分析
3.1 单片机
单片机采用CH32V307VCT6的芯片,CH32V307系列是基于32位RISC-V设计的互联型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度。最高 144MHz 系统主频/支持单周期乘法和硬件除法,支持硬件浮点运算 ( FPU )/64 KB SRAM,256 KB Flash/供电电压:2.5/3.3 V,GPIO 单元独立供电/多种低功耗模式:睡眠、停止、待机/上/下电复位、可编程电压检测器/2 组 18 路通用 DMA/4 组运放比较器/1 个随机数发生器 TRNG/2 组 12 位 DAC 转换/2 单元 16 通道 12 位 ADC 转换,16 路触摸按键 TouchKey/10 组定时器/USB2.0 全速 OTG 接口/USB2.0 高速主机/设备接口( 480 Mbps 内置 PHY )/3 个 USART 接口和 5 个 UART 接口/2 个 CAN 接口( 2.0B 主动)/SDIO 接口、FSM C接口、DVP 数字图像接口


3.1 GPS北斗双模定位ATGM336H
ATGM336H-5N系列模块是小尺寸的高性能BDS/GNSS全星座定位 导航模块系列的总称。该系列模块产品都是基于中科微第四代低功耗GNSS SOC单芯片—AT6558,支持多种卫星导航,包括中国的BDS(北斗卫星 导航),美国的GPS,俄罗斯的GLONASS,欧盟的GALILEO,日本的QZSS 以及卫星增强SBAS(WAAS,EGNOS,GAGAN,MSAS)。AT6558 是一 款真正意义的六合一多模卫星导航定位芯片,包含32 个跟踪通道,可以同时接 收六个卫星导航的GNSS 信号,并且实现联合定位、导航与授时。 ATGM336H-5N本系列模块具有高灵敏度、低功耗、低成本等优势。

3.2 传感器 MPU6050和AHT10
AHT10 是一款高精度,完全校准,贴片封装的温湿度传感器。AHT10 通信方式采用标准 IIC 通信方式,支持较宽的工作电源电压范围,温湿度传感器均在高精度的恒温恒湿腔室中进行出厂校准,直接输出经温度补偿后的湿度、温度等信息,用户无需要对湿度进行温度补偿,便可得到准确的温湿度信息。
mpu6050一般指MPU-6050。 MPU-6000(6050)为全球首例整合性6轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速器时间轴之差的问题,减少了大量的封装空间。

3.3 LCD 显示模块
ST7789是直接可以驱动LCD的原始接口,ST7789V2是一个单芯片TFT-LCD驱动器。该芯片可以直接连接到外部MCU,支持并行8080系列的8位/9位/16位/18位接口,也支持SPI串行通讯接口。 显示数据可以存储在240x320x18bits的片上显示数据RAM中。 在本设计中使用的FSMC接口对单片机进行驱动设计。

3.4  通信模块
这里的通信模块包括ESP8266和CH9131两个部分。
ESP8266是一款高性能的WIFI串口模块,内部集成MCU能实现单片机之间串口通信,是目前使用最广泛的一种WIFI模块之一。
CH9141内部集成了BLE协议栈,无需编程,即可轻松实现串口和蓝牙数据包的双向透明传输,借助CH9141蓝牙串口转换模块,客户可以快速实现串口设备的蓝牙无线通信,大大降低串口设备扩展蓝牙接口难度并缩短蓝牙产品开发周期。

4、 软件设计
4.1 总体流程图

4.2 主程序设计
主要的程序包括LCD 、GPS、MPU6050、ESP8266、AHT11的系统初始化,以及各种数据的读取。
通信使用MQTT通信协议,将数据发送到服务端,并接受服务器发送过来的 告警指令。
初始了CH9141模块,将数据发送到其他终端,实现与其他终端设备的交互。
int main(void) {
    char s_Str[256];
    float temperature, humidity;
    u32 last_time0 = 0;
    u32 last_time1 = 0;

    short aacx, aacy, aacz; //加速度原始数据
    short gyrox, gyroy, gyroz; //陀螺仪原始数据
    short temp; //温度
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    Delay_Init();
    USART_Printf_Init(115200);
    lcd_init();
    lcd_set_color(WHITE, GREEN);
    lcd_set_color(BLACK, WHITE);
    uart6_init(115200); //ESP8266
    TIM2_Init(144, 1000);
    AHT10_Init(); //初始化AHT10
    LED_GPIO_Init();
    USART4_CFG();

    DMA_INIT();
    USARTx_CFG(); /* USART INIT */
    USART_DMACmd(UART7, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
    GPIO_CFG();
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, RESET); //进入 AT
    GPIO_WriteBit(GPIOC, GPIO_Pin_13, SET); //enable CH9141
    Delay_Ms(1000);
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, SET); // 退出AT。可用手机或电脑连接CH9141,测试数据收发
    while (SD_Init()) {
        printf("SD Card Error!\r\n");
    }
    show_sdcard_info();
    test_SD();
    BMP_ShowPicture("test.bmp");
    AliIoT_Parameter_Init();
    init_ESP8266();
    u8 led_cnt = 0;

    while (1) {
        if (get_tDiff(last_time0) > 5000) {
            last_time0 = timer_cnt;
            temperature = AHT10_Read_Temperature();
            humidity = AHT10_Read_Humidity();
            temp = MPU_Get_Temperature(); //获得温度
            MPU_Get_Accelerometer( & aacx, & aacy, & aacz); //获得加速度原始数据

            MPU_Get_Gyroscope( & gyrox, & gyroy, & gyroz); //获得陀螺仪原始数据
            lcd_set_color(BLACK, GREEN);
            lcd_show_string(10, 222, 16, "Temp:%2d'C", (int)(temperature));
            lcd_show_string(120, 222, 16, "Humi:%2d %%", (int)(humidity));
            if (Connnect_flag == 1) {
                sprintf(s_Str, "{\"id\":\"No.1\",\"temp\":%0.1f,\"Humidity\":%0.1f,\"Longitude\":%0.6f,\"Latitude\":%0.6f}",
                    temperature, humidity, now_lon, now_lat);
                MQTT_PublishData("/property/post", s_Str, 0);
            }
            sprintf(s_Str, "{\"t\":%d,\"h\":%d},\"Longitude\":%0.6f,\"Latitude\":%0.6f\r\n", (int)(temperature), (int)(humidity), now_lon, now_lat);
            while (uartWriteBLEstr(s_Str) == RESET);
        }

        if (get_tDiff(last_time1) > 500) {
            last_time1 = timer_cnt;
            if (led_cnt > 0) {
                if (led_cnt % 2 == 0) {
                    GPIO_ResetBits(GPIOE, GPIO_Pin_11);
                    GPIO_ResetBits(GPIOE, GPIO_Pin_12);
                } else {

                    GPIO_SetBits(GPIOE, GPIO_Pin_11);
                    GPIO_SetBits(GPIOE, GPIO_Pin_12);
                }
                led_cnt--;
            }
        }
        if (USART6_RX_OK == 1) {
            USART6_RX_OK = 0;
            USART6_RX_STA = 0;
            if (strstr(usart6_rxbuf + 4, "\"state\":1"))
                led_cnt = 10;
            memset(usart6_rxbuf, 0, USART6_MAX);
        }

        if (GPS_RX_OK) {
            GPS_RX_OK = 0;
            GPS_RX_STA = 0;
            GPS_Analysis( & gpsx, (u8 * ) GPS_RX_BUF); //分析字符串
            now_lon=(float)gpsx.longitude/100000;
            now_lat=(float)gpsx.latitude/100000;
            memset(GPS_RX_BUF, 0, sizeof(GPS_RX_BUF));
            printf("Lon:%f  ", (float) gpsx.longitude / 100000);
            printf("Lat:%f \r\n ", (float) gpsx.latitude / 100000);

        }

    }
}

4.3 网络通信
这里使用的ESP8266实现的 MQTT通信协议,使用的是AT指令。
MQTT(Message Queuing Telemetry Transport) 消息队列遥测传输协议,是一个基于客户端-服务器的消息发布/订阅传输协议。
主要的概念有5个:
Broker 代理:MQTT 服务器
Publish 发布者:客户端
Subscribe 订阅者:客户端,可订阅多个 topic
Topic 主题:消息的类型,订阅主题之后就可以收到该 topic 的消息内容即 payload
Payload 消息内容:具体的内容
服务区段部署EMQX 开源版。
全球下载量超千万的开源物联网 MQTT 服务器,高效可靠连接海量物联网设备,高性能实时处理消息与事件流数据,可运行在公有云、私有云和混合云上。EMQ X (Erlang/Enterprise/Elastic MQTT Broker) 是基于 Erlang/OTP 平台开发的开源物联网 MQTT 消息服务器。Erlang/OTP 是出色的软实时(Soft-Realtime)、低延时(Low-Latency)、分布式(Distributed) 的语言平台。MQTT 是轻量的(Lightweight)、发布订阅模式(PubSub) 的物联网消息协议。
访问 emqx.io (opens new window)或 Github (opens new window)下载要安装的 EMQX 的 tar.gz 包。
解压程序包

tar -zxf emqx-full-package-name.tar.gz

        Copied!
   
启动 EMQX Broker

cd ./emqx
./bin/emqx start
./bin/emqx_ctl status

ESP8266要实现的功能为,具体功能见代码。
extern void ESP8266_ATSendBuf(uint8_t* buf,uint16_t len);                //向ESP8266发送指定长度数据
extern void ESP8266_ATSendString(char* str);                                                                //向ESP8266模块发送字符串
extern void ESP8266_ExitUnvarnishedTrans(void);                                                        //ESP8266退出透传模式
extern uint8_t ESP8266_ConnectAP(char* ssid,char* pswd);                //ESP8266连接热点
extern uint8_t ESP8266_ConnectServer(char* mode,char* ip,uint16_t port);        //使用指定协议(TCP/UDP)连接到服务器
extern void Reset_ESP8266_RxBuffer(void);
extern uint8_t Sent2Client(char *context);
extern uint8_t ESP8266_Status(void);
uint8_t DisconnectServer(void);
4.4 GPS数据解析
这里使用定时器判断一帧数据是否接收完成。
配置串口3波特率为9600,并启动中断接收数据。
void USART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART3_IRQHandler(void)
{
    u8 uartR=0;

        uartR= USART_ReceiveData(USART3);
        flag_rx1=1;
               rx_cnt1=0;
               if(GPS_RX_STA<GPS_MAX_RECV_LEN)   //还可以接收数据
               {
                   GPS_RX_BUF[GPS_RX_STA++]=uartR;  //记录接收到的值
               } else
               {
                   GPS_RX_OK=1;             //强制标记接收完成
               }
        USART_ClearFlag(USART3, USART_IT_RXNE); //清除标志位;
    }
}
在定时器内部进行计数,判断数据接收完成。
void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查TIM2中断是否发生。
      {
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);    //清除TIM2的中断挂起位。
        timer_cnt++;
        if(flag_rx1>0)//说明在收数据
        {
           rx_cnt1++;
           if(rx_cnt1>20)
           {
               flag_rx1=0;
               rx_cnt1=0;
               GPS_RX_OK=1;             //强制标记接收完成
           }
        }
      }
}
GPS解析数据,使用的是正点原子的代码。
//分析GPRMC信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void NMEA_GPRMC_Analysis(nmea_msg *gpsx,u8 *buf)
{
        u8 *p1,dx;                        
        u8 posx;     
        u32 temp;           
        float rs;  
        p1=(u8*)strstr((const char *)buf,"GNRMC");//"$GPRMC",经常有&和GPRMC分开的情况,故只判断GPRMC.
        posx=NMEA_Comma_Pos(p1,1);                                                                //得到UTC时间
        if(posx!=0XFF)
        {
                temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx);                 //得到UTC时间,去掉ms
                gpsx->utc.hour=temp/10000;
                gpsx->utc.min=(temp/100)%100;
                gpsx->utc.sec=temp%100;                  
        }        
        posx=NMEA_Comma_Pos(p1,3);                                                                //得到纬度
        if(posx!=0XFF)
        {
                temp=NMEA_Str2num(p1+posx,&dx);                          
                gpsx->latitude=temp/NMEA_Pow(10,dx+2);        //得到°
                rs=temp%NMEA_Pow(10,dx+2);                                //得到'                 
                gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为°
        }
        posx=NMEA_Comma_Pos(p1,4);                                                                //南纬还是北纬
        if(posx!=0XFF)gpsx->nshemi=*(p1+posx);                                         
         posx=NMEA_Comma_Pos(p1,5);                                                                //得到经度
        if(posx!=0XFF)
        {                                                                                                  
                temp=NMEA_Str2num(p1+posx,&dx);                          
                gpsx->longitude=temp/NMEA_Pow(10,dx+2);        //得到°
                rs=temp%NMEA_Pow(10,dx+2);                                //得到'                 
                gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为°
        }
        posx=NMEA_Comma_Pos(p1,6);                                                                //东经还是西经
        if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);                 
        posx=NMEA_Comma_Pos(p1,9);                                                                //得到UTC日期
        if(posx!=0XFF)
        {
                temp=NMEA_Str2num(p1+posx,&dx);                                                 //得到UTC日期
                gpsx->utc.date=temp/10000;
                gpsx->utc.month=(temp/100)%100;
                gpsx->utc.year=2000+temp%100;                  
        }
}
4.5 传感器数据
这里设置的平均5s读取一次数据
if(get_tDiff(last_time0)>5000){
            last_time0=timer_cnt;
            temperature = AHT10_Read_Temperature();
            humidity = AHT10_Read_Humidity();
            temp=MPU_Get_Temperature(); //获得温度
            MPU_Get_Accelerometer(&aacx,&aacy,&aacz);   //获得加速度原始数据
            MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);    //获得陀螺仪原始数据
            lcd_set_color(BLACK,GREEN);
            lcd_show_string(10, 222, 16, "Temp:%2d'C", (int)(temperature));
            lcd_show_string(120, 222, 16,"Humi:%2d %%", (int)(humidity));
        }
4.6  加载地图
使用SD卡内部的图片加载地图并实现。参考正点原子的样式。
void BMP_ShowPicture(uint8_t *dir)
{
        FRESULT res;
        FIL fsrc;
        UINT  br;

        uint8_t rgb;
        BMP_HeaderTypeDef bmpHeader;

        uint16_t a, x, y, color=0, width, xCount;
        float xRatio, yRatio;
        printf("pictest.bmp\r\n");
        /* 将屏幕刷黑色 */
        lcd_clear(BLACK);
        /* 打开要读取的文件 */
        res = f_open(&fsrc, (const TCHAR*)"test.bmp", FA_READ);
        if(res == FR_OK)   //打开成功
    {
                /* 读取BMP文件的文件信息 */
        res = f_read(&fsrc, buffer, sizeof(buffer), &br);
        printf("f_read res :%d\r\n",res);
                /* 将数组里面的数据放入到结构数组中,并排序好 */
                BMP_ReadHeader(buffer, &bmpHeader);

                /* 判断图片的大小超过TFT的大小的话,进行缩小 */
                if(((LCD_W) < bmpHeader.infoHeader.biWidth) ||
                   ((LCD_H-20) < bmpHeader.infoHeader.biHeight))
                {
                        /* 求出缩小比例 */
                        xRatio = (float)(LCD_W) / (float)bmpHeader.infoHeader.biWidth;
                        yRatio = (float)(LCD_H-20) / (float)bmpHeader.infoHeader.biHeight;
        
                /* 如果只有一边超出TFT屏的大小的话,不超出部分不进行缩小 */
                        if(xRatio > 1)
                        {
                                xRatio = 1;
                        }
                        if(yRatio > 1)
                        {
                                yRatio = 1;
                        }
                }
                else //如果图片大小小于TFT屏
                {
                        xRatio = 1;
                        yRatio = 1;
                }

                /* BMP图片的宽像素数据必须是4的倍数,如果不是那么将其补齐 */
                /* 所以这里是判断BMP图片的横坐标跳转数据。 */
                if(bmpHeader.infoHeader.biWidth % 4)
                {
                        width = bmpHeader.infoHeader.biWidth * 3 / 4;
                        width += 1;
                        width *= 4;        
                }               
                else
                {
                        width = bmpHeader.infoHeader.biWidth * 3;        
                }

                /* 初始化应用的值 */
                x = 0;
                y = 0;
                rgb = 0;
                xCount = 0;
                a = bmpHeader.fileHeader.bfOffBits;    //去掉文件信息才开始是像素数据
             while(1)  
             {      
                        /* SD卡读取一次数据的长度 */
                        while(a < 1024)
                        {                                
                                /* 将读取到的24位色转换为16位色 */
                                switch (rgb)
                                {
                                        case 0:                                 
                                                color = buffer[a] >> 3; //B
                                                break ;           
                                        case 1:         
                                                color += ((uint16_t)buffer[a] << 3) & 0X07E0;//G
                                                break;         
                                        case 2 :
                                                color += ((uint16_t)buffer[a] << 8) & 0XF800;//R         
                                                break ;
                    default:
                        break;                        
                                }
                                a++;
                                rgb++;

                                /* 如果读取完一个像素点,就写到TFT屏上面 */
                                if(rgb == 3)
                                {
                                    /* 设置要写入的点 */
                                    lcd_address_set((u16)((float)x * xRatio + 0.5), LCD_H-20-(u16)((float)y * yRatio + 0.5),
                                            (u16)((float)x * xRatio + 0.5),  LCD_H-20-(u16)((float)y * yRatio + 0.5));
                                        //LCD_WriteData_Color(color);
                                    lcd_write_data(color >> 8);
                                    lcd_write_data(color&0xff);

                                        rgb =0;
                                        x++;       //X坐标+1                                       
                                }

                                /* 计数一共读取了多少像素值 */
                                xCount++;
                                if(xCount >= width)           //如果等于一行的像素了,那么换行显示
                                {        
                                        xCount = 0;
                                        x = 0;
                                        y++;
                                }                                
                        }

                        /* 继续读取图片数据 */
                        res = f_read(&fsrc, buffer, sizeof(buffer), &br);
                        a = 0;

                        /* 判断手否读取完结,若完结跳出循环 */
            if (res || br < sizeof(buffer))
                        {
                                break;    // error or eof
                        }

        }
    }
         
    f_close(&fsrc);  //不论是打开,还是新建文件,一定记得关闭
}
4.7 CH9141通信模块使用的官网提供的例程,使用串口7和DMA通信的方式。
/*******************************************************************************
* Function Name  :  uartWriteBLE
* Description    :  send data to BLE via UART7          向蓝牙模组发送数据
* Input          :  char * data          data to send   要发送的数据的首地址
*                   uint16_t num         number of data 数据长度
* Return         :  RESET                UART7 busy,failed to send  发送失败
*                   SET                  send success               发送成功
*******************************************************************************/
FlagStatus uartWriteBLE(char * data , uint16_t num)
{
    //如上次发送未完成,返回
    if(DMA_GetCurrDataCounter(DMA2_Channel8) != 0){
        return RESET;
    }

    DMA_ClearFlag(DMA2_FLAG_TC8);
    DMA_Cmd(DMA2_Channel8, DISABLE );           // 关 DMA 后操作
    DMA2_Channel8->MADDR = (uint32_t)data;      // 发送缓冲区为 data
    DMA_SetCurrDataCounter(DMA2_Channel8,num);  // 设置缓冲区长度
    DMA_Cmd(DMA2_Channel8, ENABLE);             // 开 DMA
    return SET;
}

/*******************************************************************************
* Function Name  :  uartWriteBLEstr
* Description    :  send string to BLE via UART7    向蓝牙模组发送字符串
* Input          :  char * str          string to send
* Return         :  RESET                UART7 busy,failed to send  发送失败
*                   SET                  send success               发送成功
*******************************************************************************/
FlagStatus uartWriteBLEstr(char * str)
{
    uint16_t num = 0;
    while(str[num])num++;           // 计算字符串长度
    return uartWriteBLE(str,num);
}
4.9 服务前段设计。
加载百度地图引入paho-mqtt。参考文档地址:  https://www.eclipse.org/paho/files/jsdoc/Paho.MQTT.Client.html
JavaScript应用程序使用Paho.MQTT与服务器通信。客户端对象。
大多数应用程序只创建一个Client对象,然后调用其connect()方法,但是如果需要,应用程序可以创建多个Client对象。在这种情况下,每个客户端对象的主机、端口和clientId属性的组合必须不同。
发送、订阅和取消订阅方法被实现为异步JavaScript方法(即使底层协议交换本质上可能是同步的)。这意味着它们通过调用应用程序(通过应用程序提供的有关方法的成功或失败回调函数)来发出完成的信号。这种回调在每个方法调用中最多调用一次,并且不会持续到调用脚本的生命周期之外。
相比之下,Paho.MQTT上定义了一些回调函数,尤其是onMessageArrived。客户端对象。这些方法可能会被多次调用,并且与客户端进行的特定方法调用没有直接关系。

  <script src="https://cdn.bootcss.com/paho-mqtt/1.0.2/mqttws31.min.js" type="text/javascript"></script> 
  <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js"></script>
     <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=5E5EE28a7615536d1ffe2ce2a3667859"></script>
        <!--加载鼠标绘制工具-->
        <script type="text/javascript" src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js"></script>
        <link rel="stylesheet"  />
        <!--加载检索信息窗口-->
        <script type="text/javascript" src="http://api.map.baidu.com/library/SearchInfoWindow/1.4/src/SearchInfoWindow_min.js"></script>
        <link rel="stylesheet"  />
        <script type="text/javascript" src="http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js"></script>


在百度地图中加载设备标记。
      var point = new BMap.Point(lon, lat);
                                                var marker = new BMap.Marker(point);
                                                marker.addEventListener("click",
                                                        function(e) {
                                                                geoc.getLocation(e.point,
                                                                        function(rs) {
                                                                                var status;
                                                                                var content = '<div>'+ '<p>' + '<b>温度:</b>' + temp + '</p>' + '<p>' + '<b>湿度:</b>' +humi + '</p>' + '</div>';//创建信息窗口
                                                                                var opts = {
                                                                                                                        width: 80,// 信息窗口宽度
                                                                                height: 150,// 信息窗口高度
                                                                                title: '<h4 style="color: #00a65a"><strong>场面设备'+id+'监控</strong></h4>',// 信息窗口标题
                                                                                }
                                                                                var infoWindow = new BMap.InfoWindow(content, opts);
                                                                                // 创建信息窗口对象
                                                                                map.openInfoWindow(infoWindow, e.point);
                                                                                // 打开信息窗口
                                                                        }
                                                                );
                                                        }
                                                );
                                                                                                planeMarkers[1] = marker;
                                                map.addOverlay(marker);        
如何判断该地面设备处于禁区之内的判断代码
for(var i = 0; i < overlays.length; i++){
    if(BMapLib.GeoUtils.isPointInPolygon(point, overlays[i])) {
   inrange++;
     }else{
    }
  }
发送告警信息
client.send("/sys/property/set", payload='{ "state":1}', qos=0);
显示效果

5. 最终的显示效果




演示视频
https://www.bilibili.com/video/BV1y44y1Z7uY/?share_source=copy_web

  

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 150.00 元 2023-01-16
理由:恭喜通过原创审核!期待您更多的原创作品~

相关帖子

沙发
wilhelmina2| | 2023-1-9 09:48 | 只看该作者
这个姿态解算是怎么实现的?              

使用特权

评论回复
板凳
eefas| | 2023-1-9 09:58 | 只看该作者
单片机的性能怎么样?              

使用特权

评论回复
地板
bestwell| | 2023-1-9 13:08 | 只看该作者
这个地图是怎么实现的?              

使用特权

评论回复
5
fengm| | 2023-1-9 15:57 | 只看该作者
使用什么通信协议呢?              

使用特权

评论回复
6
chenci2013| | 2023-1-9 17:54 | 只看该作者
服务区使用什么搭建的?              

使用特权

评论回复
7
lloyd-123| | 2024-4-16 13:47 | 只看该作者
有偿求源代码作品一点思路都没

使用特权

评论回复
8
duhemayi| | 2024-9-7 11:26 | 只看该作者

使用特权

评论回复
发新帖 本帖赏金 150.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

535

主题

9633

帖子

23

粉丝