OpenHarmony源码分析之分布式软总线:msg_get_deviceid.c文件分析

📌往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)

①📖 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

②📖嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

③📖 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

④📖 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

⑤📖 记录一场鸿蒙开发岗位面试经历~

⑥📖 持续更新中……


一、概述

该文件代码的功能主要是提供以cJSON格式获取各个设备的信息,包括设备id、链接信息、设备名、设备类型等。下面将对该文件的每一个函数进行详细分析。

二、源码分析

msg_get_deviceid.c

/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "msg_get_deviceid.h"
#include "message.h"
#define CMD_TAG "TECmd"
#define DATA_TAG "TEData"
#define DEVICEID_TAG "TEDeviceId"
#define CMD_GET_AUTH_INFO "getAuthInfo"
#define CMD_RET_AUTH_INFO "retAuthInfo"
#define DEVICE_CONN_CAP_WIFI 0x1f
#if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__)
#define DEVICE_TYPE_DEFAULT "DEV_L0"
#else
#define DEVICE_TYPE_DEFAULT "DEV_L1"
#endif
/*
函数功能:将deviceId打包成json格式的Get消息
函数参数:
    devInfo:本地设备信息
    cmd:Get命令内容
函数返回值:
    成功:返回封装好的cJSON格式的消息
    失败:返回NULL
详细:
*/
static cJSON *MsgGetDeviceIdpack(const DeviceInfo *devInfo, const char *cmd)
{
    cJSON *msg = cJSON_CreateObject();//创建一个cJSON对象
    if (msg == NULL) {
        return NULL;
    }
    if (cJSON_AddStringToObject(msg, CMD_TAG, cmd) == NULL) {//添加一个string类型的成员到cJSON对象msg中,键为CMD_TAG,值为传入cmd的值
        cJSON_Delete(msg);
        return NULL;
    }
    if (cJSON_AddStringToObject(msg, DATA_TAG, devInfo->deviceId) == NULL) {//添加一个string类型的成员到cJSON对象msg中,键为DATA_TAG,值为deviceId
        cJSON_Delete(msg);
        return NULL;
    }
    return msg;
}
/*
函数功能:解析消息获取设备id(deviceId)和认证id(authId)
函数参数:
    msg:接收到的cJSON消息
    conn:认证设备连接信息
    cmd:命令
函数返回值:
    成功:返回0
    失败:返回-1
详细:
*/
static int MsgGetDeviceIdunpack(const cJSON *msg, AuthConn *conn, const char *cmd)
{
    char *msgCmd = GetJsonString(msg, CMD_TAG);//获取消息中键为CMD_TAG的值
    char *msgData = GetJsonString(msg, DATA_TAG);//获取消息中键为DATA_TAG的值
    char *msgAuthId = GetJsonString(msg, DEVICEID_TAG);//获取消息中键为DEVICEID_TAG的值
    if (msgCmd == NULL || msgData == NULL || msgAuthId == NULL) {//若数据包不合法,则返回-1
        return -1;
    }
    if (strcmp(msgCmd, cmd) != 0) {//如果消息中命令与传入的命令不符,则返回-1
        return -1;
    }
    if (strcpy_s(conn->deviceId, sizeof(conn->deviceId), msgData) != EOK) {//将消息中的msgData拷贝给认证设备连接的设备id
        return -1;
    }
    if (strcpy_s(conn->authId, sizeof(conn->authId), msgAuthId) != EOK) {//将消息中的msgAuthId拷贝给认证设备连接的认证id
        return -1;
    }
    return 0;
}
/*函数功能:解析消息获取设备id(deviceId)和认证id(authId)*/
int MsgGetDeviceIdUnPack(const cJSON *msg, AuthConn *conn)
{
    if (msg == NULL || conn == NULL) {
        return -1;
    }
    int ret = MsgGetDeviceIdunpack(msg, conn, CMD_GET_AUTH_INFO);
    if (ret != 0) {
        return -1;
    }
    return 0;
}
/*函数功能:将deviceId打包成json格式的Get消息*/
cJSON *MsgGetDeviceIdPack(const DeviceInfo *devInfo)
{
    if (devInfo == NULL) {
        return NULL;
    }
    return MsgGetDeviceIdpack(devInfo, CMD_RET_AUTH_INFO);
}
/*
函数功能:打包验证IP的消息,封装成cJSON格式的消息
函数参数:
    connInfo:普通连接信息
    devInfo:本地设备信息
    authPort:认证端口
    sessionPort:会话端口
函数返回值:
    成功:返回封装好的cJSON格式的消息
    失败:返回NULL
详细:
*/
cJSON* MsgVerifyIpPack(const ConnInfo *connInfo, const DeviceInfo *devInfo, int authPort, int sessionPort)
{
    if (connInfo == NULL || devInfo == NULL) {
        return NULL;
    }
    cJSON *msg = cJSON_CreateObject();//创建一个cJSON对象
    if (msg == NULL) {
        return NULL;
    }
    if (cJSON_AddNumberToObject(msg, "CODE", CODE_VERIFY_IP) == NULL) {//添加成员"CODE"
        goto ERR_EXIT;
    }
    if (cJSON_AddNumberToObject(msg, "BUS_MAX_VERSION", connInfo->maxVersion) == NULL) {//添加成员"BUS_MAX_VERSION"
        goto ERR_EXIT;
    }
    if (cJSON_AddNumberToObject(msg, "BUS_MIN_VERSION", connInfo->minVersion) == NULL) {//添加成员"BUS_MIN_VERSION"
        goto ERR_EXIT;
    }
    if (cJSON_AddNumberToObject(msg, "AUTH_PORT", authPort) == NULL) {//添加成员"AUTH_PORT"
        goto ERR_EXIT;
    }
    if (cJSON_AddNumberToObject(msg, "SESSION_PORT", sessionPort) == NULL) {//添加成员"SESSION_PORT"
        goto ERR_EXIT;
    }
    if (cJSON_AddNumberToObject(msg, "CONN_CAP", DEVICE_CONN_CAP_WIFI) == NULL) {//添加成员"CONN_CAP"
        goto ERR_EXIT;
    }
    if (cJSON_AddStringToObject(msg, "DEVICE_NAME", devInfo->deviceName) == NULL) {//添加成员"DEVICE_NAME"
        goto ERR_EXIT;
    }
    if (cJSON_AddStringToObject(msg, "DEVICE_TYPE", DEVICE_TYPE_DEFAULT) == NULL) {//添加成员"DEVICE_TYPE"
        goto ERR_EXIT;
    }
    if (cJSON_AddStringToObject(msg, "DEVICE_ID", devInfo->deviceId) == NULL) {//添加成员"DEVICE_ID"
        goto ERR_EXIT;
    }
    if (cJSON_AddStringToObject(msg, "VERSION_TYPE", devInfo->version) == NULL) {//添加成员"VERSION_TYPE"
        goto ERR_EXIT;
    }
    return msg;
ERR_EXIT:
    if (msg != NULL) {
        cJSON_Delete(msg);
    }
    return NULL;
}
/*
函数功能:逐字段解析对端发送来的json消息,并更新相关属性结构体(如普通连接信息ConnInfo、认证连接信息AuthConn)
函数参数:
    msg:对端发送来的json格式的消息
    connInfo:设备连接信息
    conn:认证设备连接信息
函数返回值:
    成功:返回0
    失败:返回-1
详细:
*/
int MsgVerifyIpUnPack(const cJSON *msg, ConnInfo *connInfo, AuthConn *conn)
{
    if (msg == NULL || connInfo == NULL || conn == NULL) {
        return -1;
    }
    int maxVersion;
    if (GetJsonInt(msg, "BUS_MAX_VERSION", &maxVersion) != 0) {//获取消息中的最大总线版本号BUS_MAX_VERSION
        return -1;
    }
    int minVersion;
    if (GetJsonInt(msg, "BUS_MIN_VERSION", &minVersion) != 0) {//获取消息中的最小总线版本号BUS_MIN_VERSION
        return -1;
    }
    int connMaxVersion = connInfo->maxVersion;//获取当前连接的默认最大总线版本号
    int connMinVersion = connInfo->minVersion;
    if (maxVersion > connMaxVersion) {//如果对端最大总线版本号大于当前连接的默认最大总线版本号
        maxVersion = connMaxVersion;//赋予当前连接的默认最大总线版本号
    }
    if (minVersion < connMinVersion) {//如果对端最小总线版本号小于当前连接的默认最小总线版本号
        minVersion = connMinVersion;//赋予当前连接的默认最小总线版本号
    }
    conn->busVersion = maxVersion;//赋予认证连接的总线版本号为对端最大总线版本号
    connInfo->maxVersion = maxVersion;
    connInfo->minVersion = minVersion;
    char *deviceName = GetJsonString(msg, "DEVICE_NAME");//从消息中获取设备名DEVICE_NAME
    char *deviceType = GetJsonString(msg, "DEVICE_TYPE");//从消息中获取设备类型DEVICE_TYPE
    if (deviceName == NULL || deviceType == NULL) {
        return -1;
    }
    if (strcpy_s(connInfo->deviceName, sizeof(connInfo->deviceName), deviceName) != EOK) {//将设备名赋给普通连接信息结构体
        return -1;
    }
    if (strcpy_s(connInfo->deviceType, sizeof(connInfo->deviceType), deviceType) != EOK) {//将设备类型赋给普通连接信息结构体
        return -1;
    }
    if (GetJsonInt(msg, "AUTH_PORT", &(conn->authPort)) != 0) {//获取认证端口更新认证连接信息AuthConn
        return -1;
    }
    if (GetJsonInt(msg, "SESSION_PORT", &(conn->sessionPort)) != 0) {//获取会话端口更新认证连接信息AuthConn
        return -1;
    }
    return 0;
}
/*
函数功能:打包验证DeviceId的消息,封装成cJSON格式的消息
函数参数:
    info:本地设备信息
函数返回值:
    成功:返回封装好的cJSON格式的消息
    失败:返回NULL
详细:
*/
cJSON *MsgVerifyDeviceIdPack(DeviceInfo *info)
{
    if (info == NULL) {
        return NULL;
    }
    cJSON *msg = cJSON_CreateObject();//创建一个cJSON对象
    if (msg == NULL) {
        return NULL;
    }
    if (cJSON_AddNumberToObject(msg, "CODE", CODE_VERIFY_DEVID) == NULL) {//添加成员"CODE"
        cJSON_Delete(msg);
        return NULL;
    }
    if (cJSON_AddStringToObject(msg, "DEVICE_ID", info->deviceId) == NULL) {//添加成员"DEVICE_ID"
        cJSON_Delete(msg);
        return NULL;
    }
    return msg;
}
### 汽车嵌入式系统开发的技术文档、工具和教程 #### 技术文档 汽车嵌入式系统开发涉及多个层面的知识和技术积累,《汽车嵌入式系统手册_汽车先进技术译丛_2016版》提供了一套全面的理论基础,覆盖了从硬件到软件的整体设计思路[^1]。该书不仅介绍了系统的架构设计,还详细描述了通信协议的选择与实现方式,这对于理解现代车辆中的复杂网络结构至关重要。 此外,在实际工程项目中,技术文档通常会围绕具体的标准展开,例如AUTOSAR(Automotive Open System Architecture)。这一开放式的体系结构标准定义了一系列接口和服务,用于标准化ECU(Electronic Control Unit)之间的交互行为[^3]。学习并掌握这些标准对于从事汽车嵌入式开发的人来说是非常必要的。 #### 开发工具 针对汽车嵌入式系统的特殊需求,市场上存在多种专用工具支持整个开发生命周期的不同阶段: - **建模与仿真** MATLAB/Simulink 是非常流行的建模环境之一,它允许开发者创建复杂的动态系统模型,并能够自动生产符合 AUTOSAR 标准的代码[^3]。这种基于模型的设计方法显著提高了效率,减少了手动编码错误的可能性。 - **版本控制与协作** Git 和 GitHub/GitLab/Bitbucket 提供强大的分布式版本控制系统,帮助团队成员高效协同工作[^4]。特别是当面对大规模项目时,良好的版本管理策略显得尤为重要。 - **缺陷追踪与项目管理** Jira 被广泛应用于敏捷开发过程中,用来记录任务状态、分配责任以及监控进度情况[^4]。通过这种方式可以有效促进跨部门沟通合作,确保按时交付高质量产品。 - **持续集成(CI)/部署(CD)** Jenkins 或 Travis CI 这样的自动化服务器可以帮助设置流水线作业来执行单元测试、静态分析以及其他质量保障措施,从而加快反馈循环速度并降低回归风险。 #### 学习资源推荐 除了前面提到过的书籍外,“MATLAB AUTOSAR 教程”也是一个不可多得的好资料,特别适合初学者快速入门如何利用现代化工具链完成符合行业规范的应用程序构建过程[^3]。另外还可以关注一些在线教育平台如 Coursera 上开设的相关课程或者 MOOC 平台上的免费讲座系列。 --- ### 示例代码片段展示 CAN 总线消息收发逻辑 (Python) 下面给出一段简单的 Python 程序演示如何借助 can 库操作 Linux 下面的 SocketCAN 接口发送接收数据帧: ```python import cantools from can import Bus, Message def send_can_message(bus_name: str, db_file_path: str): """Send a single CAN message using the provided DBC file.""" database = cantools.database.load_file(db_file_path) bus = Bus(interface='socketcan', channel=bus_name) msg_id = 0x7DF # Example ID data_fields = {'EngineSpeed': 2500} # Field names must match those defined in your DBC try: frame = database.get_message_by_frame_id(msg_id).encode(data_fields) message_to_send = Message(arbitration_id=msg_id, data=frame, is_extended_id=False) print(f'Sending {message_to_send}') bus.send(message_to_send) finally: bus.shutdown() if __name__ == '__main__': dbc_filepath = '/path/to/database.dbc' interface_channel = 'vcan0' # Virtual CAN device name on Linux systems. send_can_message(interface_channel, dbc_filepath) ``` 此脚本依赖 `cantools` 及其底层驱动库才能正常运行,请先安装好它们再尝试调用函数功能。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值