物联网实战--平台篇之(二)基础搭建

目录

一、Qt工程创建

二、数据库知识

三、通信协议

四、名词定义


本项目的交流QQ群:701889554

物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html

物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631333.html

一、Qt工程创建

        Qt方面有三个工程需要创建,分别是应用服务器程序、数据服务器程序和客户端APP,他们各自的作用在上一篇已经说过了,这一篇主要创建工程的基础结构,主要是MQTT通讯和数据库相关等基础文件。对于应用服务器和数据服务器程序是不需要界面的,用控制台程序即可,所以它们的.pro文件都有一个:

QT -= gui

        对于MQTT之前已经有大概讲解过了,可以去参考之前的文章,我们这里主要还是对开源库进行封装,把域名解析、话题订阅、证书添加等内容进行内部处理。在这里我们主要介绍下数据库相关的内容。

物联网实战--入门篇之(七)嵌入式-MQTT_mqtt嵌入式-CSDN博客

项目工程集合 https://download.csdn.net/download/ypp240124016/89248704

二、数据库知识

        QT对各类数据库进行封装,可以驱动很多类型的数据,包括ODBC、SQLite、MySQL、PostgreSQL、SQL Server、Oracle等,不同类型的数据库驱动类型略有区别,一般数据库都需要另外安装软件,比如MySQL,可以参考这篇文章Mysql的安装配置教程(非常详细)从零基础入门到精通,看完这一篇就够了_mysql安装教程-CSDN博客

        对于没接触过数据库的同学会觉得比较麻烦,所以我们这个项目为了方便,直接使用SQLite作为数据库了,它无需额外安装软件,生成的数据库是独立文件,就像普通配置文件一样。数据库的操作,核心就是增删改查,利用数据库语句进行操作,这里可以大概看下教程SQLite 教程 | 菜鸟教程

        以下是数据库驱动SQLite的封装文件和代码:

#include "BaseSqlite.h"

BaseSqlite::BaseSqlite(QObject *parent) : QObject(parent)
{
}

BaseSqlite::~BaseSqlite()
{
//    closeDataBase();
}

void BaseSqlite::closeDataBase(void)
{
//    qDebug()<<m_dbName<<" ## "<<m_connName<<"closeDataBase";
//    QSqlDatabase::removeDatabase(m_connName);
    m_sqlDataBase.close();
}

//打开数据库
bool BaseSqlite::openDataBase(QString db_name, QString conn_name)
{
    if(m_sqlDataBase.isOpen())
    {
        qDebug()<<m_dbName<<" "<<m_connName<< " is opened.";
        return false;
    }
    m_dbName=db_name;
    m_connName=conn_name;

    if(QSqlDatabase::contains(m_connName))
      m_sqlDataBase = QSqlDatabase::database(m_connName);
    else
      m_sqlDataBase = QSqlDatabase::addDatabase("QSQLITE", m_connName);

//    m_sqlDataBase = QSqlDatabase::addDatabase("QSQLITE", conn_name);
    m_sqlDataBase.setDatabaseName(db_name);
    if(!m_sqlDataBase.open())
    {
        qDebug()<<m_dbName<<" "<<m_connName<< "Error: Failed to connect database." << m_sqlDataBase.lastError();
        return false;
    }
    else
    {
        m_sqlQuery = QSqlQuery(m_sqlDataBase);
//        qDebug()<<m_dbName<<" "<<m_connName<< "Succeed to open database." ;
    }
    return true;
}

bool BaseSqlite::isOpened(void)
{
    return m_sqlDataBase.isOpen();
}

//执行语句
bool BaseSqlite::runSqlQuery(QString str_query)
{
//    QSqlQuery query(m_sqlDataBase);

    if(!m_sqlQuery.exec(str_query))
    {
        qDebug()<<m_sqlQuery.lastError();
    }
    else
    {
        return true;
    }
    return false;
}

//启动事务
bool BaseSqlite::beginTransaction(void)
{
    QString str_query = "BEGIN TRANSACTION";
    if(runSqlQuery(str_query)==false)
    {
        return false;
    }
    return true;
}

//停止事务
bool BaseSqlite::endTransaction(void)
{
    QString str_query = "COMMIT";
    if(runSqlQuery(str_query)==false)
    {
        return false;
    }
    return true;
}



        看起来也很简单,主要就是打开、关闭数据库,执行数据库语句;另外还有启动和停止事务,主要是用于数据流比较大的场景,比如数据服务器的数据保存,用数据库的事务功能可以避免频繁打开、关闭数据库,浪费时间,可以累积数据或者定时写入数据,提高效率。

三、通信协议

        这里的通讯协议指的是应用层的协议,理论上各个公司都是自定义的,没有标准。在这里,我们从实际需求出发,也自定义了一种协议,具体如下:

        协议看着比较复杂,分成两部分来看,一个是整体定义,一个是数据包内容。首先协议采用二进制传输,整体上包含帧头,便于检索,校验码、数据长度该有的也都有了;1~16字节内容都是明文,都有相应解释,其中app_id和dev_sn稍后详细说明;17~N的数据区需要加密,我们整个系统采用一型多密的方案,即一种型号配套多组密码,根据自己需要使用,密码在设备生产定义时确定,需要注意保护,协议中的索引就是密码索引,这样可以明确数据包内用了哪一组的密码。

        协议的核心还是数据区里的内容,这里使用的是一种嵌套的思想,因为在实际项目中我们经常会用到无线组网的方式,一个网关加多个节点,对于节点数据是需要通过网关转发的,那就相当于把节点数据嵌套在网关数据内部,这时候网关的顶层命令固定为100,意思就是本次数据包是转发的节点数据,要根据数据包的内容进一步解析;下行的时候也是一样,节点的控制指令需要经过网关进行转发,转发命令固定为200,网关解析后会把数据提取出来,至于怎么转发是网关跟节点之间的事了,后面在做LoRa组网的时候会具体演示。

        理论上可以一直嵌套下去,不过一般就一层,网关+节点,节点后面再挂载节点的情况比较少见了。

        对于不同的设备会包含不同的命令类型,需要从设备的实际需求出发,一般来讲,针对每一种类型的设备或者新产品,都要有规范的协议文档,这样在开发和维护过程中比较清晰,出现问题容易定位。

        协议内容都是字节序的形式传输,避免大小端的问题,我们约定数据高位先传输,比如协议里的app_id是四个字节,以AABB1122为例,那传输顺序就是AA、BB、11、22;对于数据的定义可以参考之前的净化器数值,简单讲就是我们只传输正整数,产品定义的时候就要把某个数据的范围和精度确定好,这样就可以把这个数据转为正整数了,然后传输依然是高位在前,低位在后的原则。这样,整个协议的统一性就很高了,对于具体的代码在后续合适的章节会体现,不会很复杂。

四、名词定义

        整个体系会有一些专有名词,这里统一做一下解释。

        账户:这个不用过多解释了,就像微信号一样,在整个系统里是唯一的,一般采用字符和数字的形式,我们这个系统以手机号为核心,注册的时候需要跟手机绑定,用验证码的方式注册,属于比较常规的。

        子账户:有时候手机号就一个,账户又想要多个,那么就可以用主账户去新建子账户,子账户的使用上跟主账户类似,但是子账户不能再创建子账户了。

        应用ID:就是协议里的app_id,长度是4个字节,每个账户下可以创建多个应用,每个应用下包含多个设备,举例说明,一般来讲,智能家居中一套房子创建一个应用,这个应用下有空调、冰箱、净化器等设备,这时候假设你有多套房子,每套房子都要整一套智能家居产品,显然,如果把所有设备都放在一个应用下就不太好管理了,这时候就可以为每套房子新建一个应用,各自的设备放在对应的应用下,彼此就很好管理了,这就是应用ID存在的意义。从技术角度来讲,设备发布消息的话题形式是这样的dev/pub/data/123001,其中123001就是应用ID,这样对于用户端APP来讲,只要根据app_id来订阅,该应用下的设备数据就会发到正确的用户端。所以说,app_id在整个系统的管理上起到了一个很关键的作用。

        设备序列号:就是协议里的dev_sn,是设备的身份标识,长度是4个字节,对于dev_sn是需要规范的,不能随便定义,在这里我们定义,高2字节代表设备类型,低2字节代表地址码,例如16进制A3010001,其中A301代表设备类型,比如四路主机,这个在产品定义时就要确定,那么0001就是地址码,这是在生产时确定的,于是四路主机所有的序列号就是A3010001~A301FFFF,理论上可以生产6万多个。实际上,再加上app_id的区分,其实不要在同一个应用里使用相同的dev_sn就行了,这样一来,在实际项目中都是够用的了。我们的密码体系是一型多密原则,这里的型就是指dev_sn的高2字节,理论上可以创建6万多种型号,够用了。总体来讲,app_id和dev_sn是我们整个系统设计的核心,一切都是围绕这两个概念展开的。

        解析插件:每一种型号的设备对应一个解析插件,主要就是负责对设备数据进行解析和操作,后期的产品开发主要就是设备端和对应解析插件的开发,这也是端到端开发模式的由来。解析插件主要是对用户端APP的不断扩充,包含两个内容,一个是后端C++对数据进行解析,一个是前端QML做该型号设备的展示界面,就像入门篇里所展示的净化器界面一样。这样,平台端无需增加开发,一个简单的物联网开发模式就形成了。

        网关/主机:这一类设备是直接跟服务器连接的,它们一般带有网口、WIFI或者4G等互联网接口,设备端的加密/解密也是在这类设备中完成的;它们有时候是独立的个体,比如WiFi空调,有时候是作为其它设备的数据中转站,比如LoRa网关,主要作用就是对LoRa节点设备的数据进行转发。

        节点:与上面所述的网关配合使用,节点的特点一般是数量较多,每个都有联网功能的话成本较高,所以选择用网关作为统一的联网媒介,比如485温湿度、LoRa门磁等等。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

请编写函数fun,该函数的功能是:统计各年龄段的人数。N个年龄通过调用随机函数获得,并放在主函数的age数组中;

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 请编…

考研管理类联考(专业代码199)数学基础【2】整式与分式

一、整式及其运算 1.常用乘法公式&#xff08;逆运算就是因式分解&#xff09; 公式扩展① 公式扩展② 公式扩展③ 2.整式除法定理 若整式 F(x) 除以x-a的余式为r(x)&#xff0c;则 F(x) (x -a) g(x) r(x) &#xff0c;故r(a)F(a)成立 二、指数和对数的运算性质 1.指数运算…

vue3、element-plus递归实现动态菜单

vue3、element-plus递归实现动态菜单 使用场景&#xff1a;动态菜单为什么使用递归递归在动态菜单中的实现 使用场景&#xff1a;动态菜单 动态菜单是指菜单项的数量和层次结构可能是动态的&#xff0c;通常来自后端或用户输入。这些菜单的特征包括&#xff1a; 多层嵌套&…

Mysql从入门到精通——Mysql知识点总结(基础篇)

参考视频 黑马程序员 MySQL数据库入门到精通i 题单推荐 入门 进阶 SQL语句类型 DDL:数据定义语言&#xff0c;用来定义数据库对象(数据库&#xff0c;表&#xff0c;字段)DML:数据操作语言&#xff0c;对数据库表中的数据进行增删改DQL:数据查询语言,用来查询数据库中表的…

Linux第二节--常见的指令介绍集合(持续更新中)

点赞关注不迷路&#xff01;&#xff0c;本节涉及初识Linux第二节&#xff0c;主要为常见的几条指令介绍。 Linux下基本指令 1. ls 指令 语法&#xff1a; ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#…

VPot-Free一款功能强大的文字转语音工具 v2306

01 软件介绍 VPot-FREE是一款功能强大的免费文字转语音工具&#xff0c;为用户提供了便捷的语音合成功能。无论是想将文字转化为语音进行朗读&#xff0c;还是将文章转为语音保存&#xff0c;VPot-FREE都能满足你的需求。 多种语音风格可供选择&#xff0c;包括男声、女声以及…

笔记-用Python脚本启停JAR程序

用Python脚本启停JAR程序&#xff0c;需要用到python中的以下内置模块 subprocess 是 Python 的一个标准库模块&#xff0c;用于在新进程中执行子命令&#xff0c;获取子进程的输入/输出/错误以及返回码等os 是 Python 的一个标准库模块&#xff0c;它提供了与操作系统交互的功…

Vue---混入

Vue—混入 目录 Vue---混入声明mixin**局部使用**全局使用 mixin&#xff08;混入&#xff09;&#xff1a;可以将组件中共用的配置提取到一个对象内&#xff0c;以此便不用再每个组件中都写一遍了 声明mixin 定义mixin/index.js文件 const mixinData {data(){return {name…

Linux内核深入学习 - 中断与异常(上)

中断与异常 中断通常被定义为一个事件&#xff1a;让事件改变处理器执行的指令顺序这样的事件&#xff0c;与CPU芯片内外部硬件电路产生的电信号相对应&#xff01; 中断通常分为同步中断与异步中断&#xff1a; 同步中断指的是当指令执行时&#xff0c;由CPU控制单元产生的…

基于Java-jsp的现代数字化城市公交查询系统论文(四)

⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️ ➡️点击免费下载全套资料:源码、数据库、部署教程、论文、答辩ppt一条龙服务 ➡️有部署问题可私信联系 ⬆️⬆️⬆️​​​​​​​⬆️…

音视频入门基础:像素格式专题(1)——RGB简介

一、像素格式简介 像素格式&#xff08;pixel format&#xff09;指像素色彩按分量的大小和排列。这种格式以每个像素所使用的总位数以及用于存储像素色彩的红、绿、蓝和 alpha 分量的位数指定。在音视频领域&#xff0c;常用的像素格式包括RGB格式和YUV格式&#xff0c;本文…

a-table 控制列的展示和隐藏

一、业务场景&#xff1a; 最近在使用 Antd-vue 组件库的时候&#xff0c;a-table需要根据不同角色的权限显示和隐藏 columns的列 为了避免大家走弯路&#xff0c;为大家整理了一下&#xff0c;粘走可以直接用的那种 二、具体实现步骤&#xff1a; 1.在需要显示与隐藏的列增加一…

制定语音芯片的语音识别指令时需要关注的内容

背景 最近定义设备识别的语音指令以及对应的语音反馈。虽然语音控制在软件里只是很小的一块功能&#xff0c;但也不能太马虎。新人入坑就要学习&#xff0c;学习前人的经验规避问题&#xff0c;最后总结经验给后人&#xff0c;给未来的自己。好记性不如烂笔头~ 下面一些问题是…

1700java进销存管理系统Myeclipse开发sqlserver数据库web结构java编程计算机网页项目

一、源码特点 java web进销存管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为sqlser…

『FPGA通信接口』DDR(3)DDR3颗粒读写测试

文章目录 前言1.配套工程简介2.测试内容与策略3. 测试程序分析4.程序结果分析5.一个IP控制两颗DDR36.传送门 前言 以四颗MT41K512M16HA-125AIT颗粒为例&#xff0c;介绍如何在一块新制板卡上做关于DDR3的器件测试。前面两篇介绍了什么是DDR&#xff0c;并介绍了xilinx给出的FPG…

基于Springboot的音乐翻唱与分享平台

基于SpringbootVue的音乐翻唱与分享平台设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 音乐资讯 音乐翻唱 在线听歌 后台登录 后台首页 用户管理 音乐资讯管理…

Elasticsearch:探索 11 种流行的机器学习算法

作者&#xff1a;来自 Elastic Elastic Platform Team 过去几年中&#xff0c;机器学习&#xff08;ML&#xff09;已经悄然成为我们日常生活中不可或缺的一部分。它影响着从购物网站和流媒体网站上的个性化推荐&#xff0c;到保护我们的收件箱免受我们每天收到的大量垃圾邮件的…

3.9设计模式——Strategy 策略模式(行为型)

意图 定义一系列的算法&#xff0c;把它们一个个封装起来&#xff0c;并且使他们可以相互替换此模式使得算法可以独立于使用它们的客户而变化 结构 Strategy&#xff08;策略&#xff09;定义所有支持的算法的公共入口。Context使用这个接口来调用某ConcreteStrategy定义的方…

手撕spring框架(2)

相关系列 java中spring底层核心原理解析&#xff08;1&#xff09;-CSDN博客 java中spring底层核心原理解析(2)-CSDN博客 手撕spring框架&#xff08;1&#xff09;-CSDN博客 依赖注入原理 依赖注入(Dependency Injection&#xff0c;简称DI)是一种设计模式&#xff0c;它允许我…

DS高阶:图论基础知识

一、图的基本概念及相关名词解释 1.1 图的基本概念 图是比线性表和树更为复杂且抽象的结&#xff0c;和以往所学结构不同的是图是一种表示型的结构&#xff0c;也就是说他更关注的是元素与元素之间的关系。下面进入正题。 图是由顶点集合及顶点间的关系组成的一种数据结构&…
最新文章