From 25bb8b051474781df8f0c8b831d643eb290fbad3 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Wed, 12 Nov 2025 15:49:03 +0800 Subject: [PATCH] change to docker --- HTTP_API_README.md | 954 ++++++ README.md | 12 - apps/iot/include/endpoint.hrl | 2 +- apps/iot/include/iot.hrl | 41 - apps/iot/include/message.hrl | 93 + apps/iot/include/message_pb.hrl | 133 - apps/iot/src/database/ai_event_logs_bo.erl | 30 - apps/iot/src/database/device_bo.erl | 43 - apps/iot/src/database/endpoint_bo.erl | 97 - apps/iot/src/database/event_logs_bo.erl | 25 - apps/iot/src/database/host_bo.erl | 49 - apps/iot/src/database/micro_inform_log.erl | 17 - apps/iot/src/database/micro_service_bo.erl | 23 - apps/iot/src/database/micro_set_bo.erl | 19 - apps/iot/src/database/task_logs_bo.erl | 19 - apps/iot/src/endpoint/endpoint.erl | 104 +- apps/iot/src/endpoint/endpoint_http.erl | 12 +- apps/iot/src/endpoint/endpoint_kafka.erl | 40 +- apps/iot/src/endpoint/endpoint_mqtt.erl | 21 +- .../src/endpoint/endpoint_subscription.erl | 200 ++ apps/iot/src/endpoint/endpoint_sup.erl | 60 +- apps/iot/src/endpoint/endpoint_sup_sup.erl | 49 + .../src/http_handlers/container_handler.erl | 309 ++ apps/iot/src/http_handlers/device_handler.erl | 18 - .../src/http_handlers/endpoint_handler.erl | 22 +- .../http_handlers/event_stream_handler.erl | 47 + apps/iot/src/http_handlers/host_handler.erl | 14 - .../{http_server.erl => http_protocol.erl} | 29 +- .../iot/src/http_handlers/service_handler.erl | 146 - apps/iot/src/iot.app.src | 1 - apps/iot/src/iot_api.erl | 281 +- apps/iot/src/iot_app.erl | 54 +- apps/iot/src/iot_device.erl | 79 +- ...rver.erl => iot_event_stream_observer.erl} | 79 +- apps/iot/src/iot_host.erl | 169 +- apps/iot/src/iot_host_sup.erl | 2 +- apps/iot/src/iot_router.erl | 26 - apps/iot/src/iot_sup.erl | 24 +- apps/iot/src/message/message_codec.erl | 134 + apps/iot/src/mocker/iot_mock.erl | 9 +- apps/iot/src/mocker/iot_mqtt_consumer.erl | 281 -- apps/iot/src/protobuf/message_pb.erl | 2706 ----------------- apps/iot/src/tcp/tcp_channel.erl | 119 +- apps/iot/src/tcp/tcp_server.erl | 37 - backup/endpoint_mnesia.erl | 97 - backup/endpoint_mysql.erl | 214 -- backup/service_config_model.erl | 121 - backup/service_handler.erl | 176 -- config/sys-dev.config | 60 +- config/sys-prod.config | 26 +- docs/endpoint.md | 100 +- docs/iot_api.md | 409 +++ rebar.config | 7 +- rebar.lock | 52 +- 54 files changed, 2874 insertions(+), 5017 deletions(-) create mode 100644 HTTP_API_README.md delete mode 100644 README.md create mode 100644 apps/iot/include/message.hrl delete mode 100644 apps/iot/include/message_pb.hrl delete mode 100644 apps/iot/src/database/ai_event_logs_bo.erl delete mode 100644 apps/iot/src/database/device_bo.erl delete mode 100644 apps/iot/src/database/endpoint_bo.erl delete mode 100644 apps/iot/src/database/event_logs_bo.erl delete mode 100644 apps/iot/src/database/host_bo.erl delete mode 100644 apps/iot/src/database/micro_inform_log.erl delete mode 100644 apps/iot/src/database/micro_service_bo.erl delete mode 100644 apps/iot/src/database/micro_set_bo.erl delete mode 100644 apps/iot/src/database/task_logs_bo.erl create mode 100644 apps/iot/src/endpoint/endpoint_subscription.erl create mode 100644 apps/iot/src/endpoint/endpoint_sup_sup.erl create mode 100644 apps/iot/src/http_handlers/container_handler.erl create mode 100644 apps/iot/src/http_handlers/event_stream_handler.erl rename apps/iot/src/http_handlers/{http_server.erl => http_protocol.erl} (77%) delete mode 100644 apps/iot/src/http_handlers/service_handler.erl rename apps/iot/src/{iot_name_server.erl => iot_event_stream_observer.erl} (62%) delete mode 100644 apps/iot/src/iot_router.erl create mode 100644 apps/iot/src/message/message_codec.erl delete mode 100644 apps/iot/src/mocker/iot_mqtt_consumer.erl delete mode 100644 apps/iot/src/protobuf/message_pb.erl delete mode 100644 apps/iot/src/tcp/tcp_server.erl delete mode 100644 backup/endpoint_mnesia.erl delete mode 100644 backup/endpoint_mysql.erl delete mode 100644 backup/service_config_model.erl delete mode 100644 backup/service_handler.erl create mode 100644 docs/iot_api.md diff --git a/HTTP_API_README.md b/HTTP_API_README.md new file mode 100644 index 0000000..a987558 --- /dev/null +++ b/HTTP_API_README.md @@ -0,0 +1,954 @@ +# 🧩 IoT 容器管理接口文档 + +**模块**:`container_handler` +**作者**:licheng5 +**创建时间**:2020-04-26 +**说明**:提供容器的部署、配置、启动、停止、查询等管理 API 接口。 + +## 服务器地址 + http://127.0.0.1:18090 + +--- +## 📦 模块结构 + +| 模块 | 说明 | +|------|------| +| `container_handler` | 提供容器管理的 HTTP 接口处理 | +| `iot_util` | 工具模块,用于生成标准化 JSON 响应 | + +--- + +## ⚙️ `iot_util` 模块函数声明 + +```erlang +%%-------------------------------------------------------------------- +%% @doc +%% 将数据封装为标准 JSON 响应: +%% {"result": Data} +%%-------------------------------------------------------------------- +json_data(Data) -> + jiffy:encode(#{ + <<"result">> => Data + }, [force_utf8]). + +%%-------------------------------------------------------------------- +%% @doc +%% 生成错误响应 JSON: +%% { +%% "error": { +%% "code": ErrCode, +%% "message": ErrMessage +%% } +%% } +%%-------------------------------------------------------------------- +json_error(ErrCode, ErrMessage) when is_integer(ErrCode), is_binary(ErrMessage) -> + jiffy:encode(#{ + <<"error">> => #{ + <<"code">> => ErrCode, + <<"message">> => ErrMessage + } + }, [force_utf8]). +``` + +### 📘 返回格式说明 + +| 字段 | 说明 | +|------|------| +| `result` | 正常返回数据 | +| `error.code` | 错误代码 | +| `error.message` | 错误信息 | + +--- + +## 🌐 HTTP API 接口列表 + +以下为 `container_handler` 模块导出的全部 HTTP 接口。 + +--- + +### 1️⃣ 获取容器列表 + +**URL**:`/container/get_all` +**Method**:`GET` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | list | 容器信息列表 | + +#### 示例响应 +```json +{ + "result": [ + {"name": "container_1", "status": "running"}, + {"name": "container_2", "status": "stopped"} + ] +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": -1, + "message": "host not found" + } +} +``` + +--- + +### 2️⃣ 下发配置文件 + +**URL**:`/container/push_config` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | +| container_name | binary (string) | ✅ | 容器名称 | +| config | binary (string, JSON) | ✅ | 容器配置内容(JSON 字符串) | +| timeout | integer | ✅ | 超时时间(秒) | + +### 请求示例 +```json +{"uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm", "container_name": "my_nginx_new", "config": "{\"application\":{\"namexyz\":\"RandomConfigApp\",\"version\":\"1.2.7\",\"environment\":{\"debug_mode\":true,\"log_level\":\"info\",\"max_log_files\":10}},\"server\":{\"host\":\"127.0.0.1\",\"port\":8080,\"ssl_enabled\":false,\"allowed_origins\":[\"https:\\/\\/example.com\",\"http:\\/\\/localhost:3000\"]},\"database\":{\"type\":\"postgresql\",\"host\":\"db.example.com\",\"port\":5432,\"username\":\"admin_7xq9f\",\"password\":\"p@ssw0rd!r4nd\",\"connection_pool\":15,\"timeout_seconds\":30},\"features\":{\"enable_analytics\":true,\"enable_cache\":false,\"experimental_features\":[\"ai_enhancement\",\"realtime_sync\"]},\"third_party\":{\"api_key\":\"a3b8c2d4e5f6g7h8i9j0k1l2m3n4o5p\",\"weather_service_url\":\"https:\\/\\/api.weather.example\\/v3\",\"payment_gateway\":{\"endpoint\":\"https:\\/\\/pay.example.com\",\"merchant_id\":\"M123456789\"}},\"scheduled_tasks\":[{\"name\":\"nightly_backup\",\"cron\":\"0 3 * * *\",\"enabled\":true},{\"name\":\"log_cleanup\",\"interval_minutes\":1440,\"retention_days\":7}],\"admins\":[{\"username\":\"alice_dev\",\"email\":\"alice@example.com\",\"permissions\":[\"read\",\"write\",\"admin\"]},{\"username\":\"bob_ops\",\"email\":\"bob@example.org\",\"permissions\":[\"read\",\"audit\"]}]}", "timeout": 10} +``` + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | map | 配置结果 | + +#### 示例响应 +```json +{ + "result": { + "container_name": "sensor_service", + "status": "config pushed" + } +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": -1, + "message": "host not found" + } +} +``` + +--- + +### 3️⃣ 部署容器服务 + +**URL**:`/container/deploy` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | +| task_id | integer | ✅ | 任务 ID | +| config | map | ✅ | 部署配置内容 | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | map | 部署结果 | + +### 请求示例 +```json +{ + "uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm", + "task_id": 1, + "timeout": 10, + "config": { + "image": "docker.1ms.run/library/nginx:latest", + "container_name": "my_nginx_new", + "command": [ + "nginx", + "-g", + "daemon off;" + ], + "entrypoint": [ + "/docker-entrypoint.sh" + ], + "envs": [ + "ENV1=val1", + "ENV2=val2" + ], + "env_file": [ + "./env.list" + ], + "ports": [ + "8080:80", + "443:443" + ], + "expose": [ + "80", + "443" + ], + "volumes": [ + "/host/data:/data", + "/host/log:/var/log" + ], + "networks": [ + "mynet" + ], + "labels": { + "role": "web", + "env": "prod" + }, + "restart": "always", + "user": "www-data", + "working_dir": "/app", + "hostname": "myhost", + "privileged": true, + "cap_add": [ + "NET_ADMIN" + ], + "cap_drop": [ + "MKNOD" + ], + "devices": [ + "/dev/snd:/dev/snd" + ], + "mem_limit": "512m", + "mem_reservation": "256m", + "cpu_shares": 512, + "cpus": 1.5, + "ulimits": { + "nofile": "1024:2048" + }, + "sysctls": { + "net.ipv4.ip_forward": "1" + }, + "tmpfs": [ + "/tmp" + ], + "extra_hosts": [ + "host1:192.168.0.1" + ], + "healthcheck": { + "test": [ + "CMD-SHELL", + "curl -f http://localhost || exit 1" + ], + "interval": "30s", + "timeout": "10s", + "retries": 3 + } + } +} + +``` + +#### 示例响应 +```json +{ + "result": { + "task_id": 1001, + "status": "deployed" + } +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "host not found" + } +} +``` + +--- + +### 4️⃣ 启动容器服务 + +**URL**:`/container/start` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | +| container_name | binary (string) | ✅ | 容器名称 | + +### 请求示例 +```json +{"uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm", "container_name": "my_nginx_new"} +``` + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | map | 启动结果 | + +#### 示例响应 +```json +{ + "result": { + "container_name": "sensor_service", + "status": "started" + } +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "host not found" + } +} +``` + +--- + +### 5️⃣ 停止容器服务 + +**URL**:`/container/stop` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | +| container_name | binary (string) | ✅ | 容器名称 | + +### 请求示例 +```json +{"uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm", "container_name": "my_nginx_new"} +``` + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | map | 停止结果 | + +#### 示例响应 +```json +{ + "result": { + "container_name": "sensor_service", + "status": "stopped" + } +} +``` + +### 6 强制停止容器服务 + +**URL**:`/container/kill` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | +| container_name | binary (string) | ✅ | 容器名称 | + +### 请求示例 +```json +{"uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm", "container_name": "my_nginx_new"} +``` + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | map | 停止结果 | + +#### 示例响应 +```json +{ + "result": { + "container_name": "sensor_service", + "status": "stopped" + } +} +``` + +### 7 删除容器 + +**URL**:`/container/remove` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | +| container_name | binary (string) | ✅ | 容器名称 | + +### 请求示例 +```json +{"uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm", "container_name": "my_nginx_new"} +``` + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | map | 停止结果 | + +#### 示例响应 +```json +{ + "result": { + "container_name": "sensor_service", + "status": "stopped" + } +} +``` + + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "host not found" + } +} +``` + +--- + +### 6️⃣ 未知路径处理 + +**说明**:如果请求路径未匹配任何定义接口,将返回错误信息。 + +#### 示例响应 +```json +{ + "error": { + "code": -1, + "message": "url: /unknown/path not found" + } +} +``` + +--- + +## 🧾 返回约定总结 + +| 类型 | 说明 | +|------|------| +| `{"result": Data}` | 表示请求成功 | +| `{"error": {"code": N, "message": Text}}` | 表示请求失败 | + + + +# 🧩 IoT Endpoint 管理接口文档 + +**模块**:`endpoint_handler` +**作者**:licheng5 +**创建时间**:2020-04-26 +**说明**:用于管理 IoT Endpoint 的运行状态,包括启动、停止、重启、状态查询等。 + +--- + +## 📦 模块结构 + +| 模块 | 说明 | +|------|------| +| `endpoint_handler` | 提供 Endpoint 管理的 HTTP 接口处理 | +| `iot_util` | 工具模块,用于生成标准化 JSON 响应 | + +--- + +## ⚙️ `iot_util` 模块函数声明 + +```erlang +%%-------------------------------------------------------------------- +%% @doc +%% 将数据封装为标准 JSON 响应: +%% {"result": Data} +%%-------------------------------------------------------------------- +json_data(Data) -> + jiffy:encode(#{ + <<"result">> => Data + }, [force_utf8]). + +%%-------------------------------------------------------------------- +%% @doc +%% 生成错误响应 JSON: +%% { +%% "error": { +%% "code": ErrCode, +%% "message": ErrMessage +%% } +%% } +%%-------------------------------------------------------------------- +json_error(ErrCode, ErrMessage) when is_integer(ErrCode), is_binary(ErrMessage) -> + jiffy:encode(#{ + <<"error">> => #{ + <<"code">> => ErrCode, + <<"message">> => ErrMessage + } + }, [force_utf8]). +``` + +### 📘 返回格式说明 + +| 字段 | 说明 | +|------|------| +| `result` | 正常返回数据 | +| `error.code` | 错误代码 | +| `error.message` | 错误信息 | + +--- + +## 🌐 HTTP API 接口列表 + +以下为 `endpoint_handler` 模块导出的全部 HTTP 接口。 + +--- + +### 1️⃣ 获取 Endpoint 运行状态 + +**URL**:`/endpoint/run_statuses` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| Ids | list | ✅ | Endpoint ID 列表 | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | list | 每个 ID 对应状态:`0` 未运行,`1` 运行中 | + +#### 示例请求 +```json +[1, 2, 3] +``` + +#### 示例响应 +```json +{ + "result": [1, 0, 1] +} +``` + +--- + +### 2️⃣ 启动 Endpoint + +**URL**:`/endpoint/start` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | integer | ✅ | Endpoint 唯一 ID | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | string | 启动结果,如 `"success"` | + +#### 示例响应 +```json +{ + "result": "success" +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "endpoint not found" + } +} +``` + +--- + +### 3️⃣ 停止 Endpoint + +**URL**:`/endpoint/stop` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | integer | ✅ | Endpoint 唯一 ID | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | string | 停止结果,如 `"success"` | + +#### 示例响应 +```json +{ + "result": "success" +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "stop endpoint error" + } +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "stop endpoint error" + } +} +``` + + +--- + +### 4️⃣ 重启 Endpoint + +**URL**:`/endpoint/restart` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | integer | ✅ | Endpoint 唯一 ID | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | string | 重启结果,如 `"success"` | + +#### 示例响应 +```json +{ + "result": "success" +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "restart endpoint error" + } +} +``` + +--- + +### 5️⃣ 未知路径处理 + +**说明**:如果请求路径未匹配任何定义接口,将返回错误信息。 + +#### 示例响应 +```json +{ + "error": { + "code": -1, + "message": "url: /unknown/path not found" + } +} +``` + +--- + +## 🧾 返回约定总结 + +| 类型 | 说明 | +|------|------| +| `{"result": Data}` | 表示请求成功 | +| `{"error": {"code": N, "message": Text}}` | 表示请求失败 | + + +# 🧩 IoT Host 管理接口文档 + +**模块**:`host_handler` +**作者**:licheng5 +**创建时间**:2020-04-26 +**说明**:用于管理 IoT 主机,包括主机指标、状态查询、激活、删除、发布事件等接口。 + +--- + +## 📦 模块结构 + +| 模块 | 说明 | +|------|------| +| `host_handler` | 提供 Host 管理的 HTTP 接口处理 | +| `iot_util` | 工具模块,用于生成标准化 JSON 响应 | + +--- + +## ⚙️ `iot_util` 模块函数声明 + +```erlang +%%-------------------------------------------------------------------- +%% @doc +%% 将数据封装为标准 JSON 响应: +%% {"result": Data} +%%-------------------------------------------------------------------- +json_data(Data) -> + jiffy:encode(#{ + <<"result">> => Data + }, [force_utf8]). + +%%-------------------------------------------------------------------- +%% @doc +%% 生成错误响应 JSON: +%% { +%% "error": { +%% "code": ErrCode, +%% "message": ErrMessage +%% } +%% } +%%-------------------------------------------------------------------- +json_error(ErrCode, ErrMessage) when is_integer(ErrCode), is_binary(ErrMessage) -> + jiffy:encode(#{ + <<"error">> => #{ + <<"code">> => ErrCode, + <<"message">> => ErrMessage + } + }, [force_utf8]). +``` + +### 📘 返回格式说明 + +| 字段 | 说明 | +|------|------| +| `result` | 正常返回数据 | +| `error.code` | 错误代码 | +| `error.message` | 错误信息 | + +--- + +## 🌐 HTTP API 接口列表 + +以下为 `host_handler` 模块导出的全部 HTTP 接口。 + +--- + +### 1️⃣ 获取主机指标 + +**URL**:`/host/metric` +**Method**:`GET` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | map | 主机指标信息 | + +#### 示例响应 +```json +{ + "result": {"cpu": 20, "memory": 1024, "disk": 51200} +} +``` + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "host not found" + } +} +``` + +#### 无指标信息响应 +```json +{ + "error": { + "code": 404, + "message": "no metric info" + } +} +``` + +--- + +### 2️⃣ 查询主机状态 + +**URL**:`/host/status` +**Method**:`GET` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | map | 主机状态信息 | + +#### 示例响应 +```json +{ + "result": {"authorize_status": 1, "active": true} +} +``` + +--- + +### 3️⃣ 重新加载主机信息 + +**URL**:`/host/reload` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | string | 重新加载结果,如 `"success"` | + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "reload error" + } +} +``` + +--- + +### 4️⃣ 删除主机 + +**URL**:`/host/delete` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | string | 删除结果,如 `"success"` | + +#### 错误响应 +```json +{ + "error": { + "code": 404, + "message": "error" + } +} +``` + +--- + +### 5️⃣ 激活主机 + +**URL**:`/host/activate` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | +| auth | boolean | ✅ | `true` 激活, `false` 取消激活 | + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | string | 激活结果,如 `"success"` | + +#### 错误响应 +```json +{ + "error": { + "code": 400, + "message": "host not found" + } +} +``` + +--- + +### 6️⃣ 发布主机事件 + +**URL**:`/host/pub` +**Method**:`POST` + +#### 请求参数 +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| uuid | binary (string) | ✅ | 主机唯一标识符 | +| topic | binary (string) | ✅ | 事件主题 | +| content | binary (string) | ✅ | 发布内容 | + +### 请求示例 +```json +{"uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm", "topic": "/device/1234/all", "content": "this is a topic payload", "timeout": 10} +``` + +#### 响应参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| result | string | 发布结果,如 `"success"` | + +#### 错误响应 +```json +{ + "error": { + "code": 400, + "message": "host not found" + } +} +``` + +--- + +### 7️⃣ 未知路径处理 + +**说明**:如果请求路径未匹配任何定义接口,将返回错误信息。 + +#### 示例响应 +```json +{ + "error": { + "code": -1, + "message": "url: /unknown/path not found" + } +} +``` + +--- + +## 🧾 返回约定总结 + +| 类型 | 说明 | +|------|------| +| `{"result": Data}` | 表示请求成功 | +| `{"error": {"code": N, "message": Text}}` | 表示请求失败 | diff --git a/README.md b/README.md deleted file mode 100644 index 22ca0a3..0000000 --- a/README.md +++ /dev/null @@ -1,12 +0,0 @@ -iot -===== - -An OTP application - -## erlang client sdk - https://github.com/emqx/emqtt - -Build ------ - - $ rebar3 compile diff --git a/apps/iot/include/endpoint.hrl b/apps/iot/include/endpoint.hrl index 5676be8..49a33aa 100644 --- a/apps/iot/include/endpoint.hrl +++ b/apps/iot/include/endpoint.hrl @@ -33,7 +33,7 @@ -record(endpoint, { id :: integer(), %% 全局唯一,在路由规则中通过名称来指定 - name :: binary(), + matcher :: binary(), %% 标题描述 title = <<>> :: binary(), %% 配置项, 格式: #{<<"protocol">> => <<"http|https|ws|kafka|mqtt">>, <<"args">> => #{}} diff --git a/apps/iot/include/iot.hrl b/apps/iot/include/iot.hrl index adc46ce..ac02e04 100644 --- a/apps/iot/include/iot.hrl +++ b/apps/iot/include/iot.hrl @@ -23,51 +23,10 @@ -define(TASK_STATUS_FAILED, 0). %% 离线 -define(TASK_STATUS_OK, 1). %% 在线 -%% efka主动发起的消息体类型, 消息大类 --define(PACKET_REQUEST, 16#01). --define(PACKET_RESPONSE, 16#02). - -%% 服务器基于pub/sub的消息, 消息大类 --define(PACKET_PUB, 16#03). - -%% push调用不需要返回, 消息大类 --define(PACKET_COMMAND, 16#04). - -%% 服务器端推送消息 --define(PACKET_ASYNC_CALL, 16#05). --define(PACKET_ASYNC_CALL_REPLY, 16#06). - -%% ping包,客户端主动发起 --define(PACKET_PING, 16#FF). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% 二级分类定义 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 主机端上报数据类型标识 --define(METHOD_AUTH, 16#01). --define(METHOD_DATA, 16#02). --define(METHOD_PING, 16#03). --define(METHOD_INFORM, 16#04). --define(METHOD_EVENT, 16#05). --define(METHOD_PHASE, 16#06). --define(METHOD_REQUEST_SERVICE_CONFIG, 16#07). - -%%%% 命令类型子分类, 不需要返回值 - -%% 授权 --define(COMMAND_AUTH, 16#08). - -%%%% 主动推送的消息类型子分类, 需要返回值 - --define(PUSH_DEPLOY, 16#01). --define(PUSH_START_SERVICE, 16#02). --define(PUSH_STOP_SERVICE, 16#03). - --define(PUSH_SERVICE_CONFIG, 16#04). --define(PUSH_INVOKE, 16#05). --define(PUSH_TASK_LOG, 16#06). - %% 缓存数据库表 -record(kv, { key :: binary(), diff --git a/apps/iot/include/message.hrl b/apps/iot/include/message.hrl new file mode 100644 index 0000000..804148c --- /dev/null +++ b/apps/iot/include/message.hrl @@ -0,0 +1,93 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% 扩展部分, 1: 支持基于topic的pub/sub机制; 2. 基于target的单点通讯和广播 +%%% @end +%%% Created : 21. 4月 2025 17:28 +%%%------------------------------------------------------------------- +-author("anlicheng"). + +%% efka主动发起的消息体类型, 消息大类 +-define(PACKET_REQUEST, 16#01). +-define(PACKET_RESPONSE, 16#02). + +%% efka主动发起不需要返回的数据 +-define(PACKET_CAST, 16#03). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% 二级分类定义 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 主机端上报数据类型标识 +-define(MESSAGE_AUTH_REQUEST, 16#01). +-define(MESSAGE_AUTH_REPLY, 16#02). + +-define(MESSAGE_COMMAND, 16#03). +-define(MESSAGE_DEPLOY, 16#04). +-define(MESSAGE_PUB, 16#05). + +-define(MESSAGE_DATA, 16#06). +-define(MESSAGE_EVENT, 16#07). + +%% efka主动上报的event-stream流, 单向消息,主要是: docker-create的实时处理逻辑上报 +-define(MESSAGE_EVENT_STREAM, 16#08). + +-define(MESSAGE_JSONRPC_REQUEST, 16#F0). +-define(MESSAGE_JSONRPC_REPLY, 16#F1). + +%%%% 命令类型子分类, 不需要返回值 +%% 授权 +-define(COMMAND_AUTH, 16#08). + +-record(auth_request, { + uuid :: binary(), + username :: binary(), + salt :: binary(), + token :: binary(), + timestamp :: integer() +}). + +-record(auth_reply, { + code :: integer(), + payload :: binary() +}). + +-record(pub, { + topic :: binary(), + content :: binary() +}). + +-record(command, { + command_type :: integer(), + command :: binary() +}). + +-record(jsonrpc_request, { + method :: binary(), + params = <<>> :: any() +}). + +-record(jsonrpc_reply, { + result :: any() | undefined, + error :: any() | undefined +}). + +-record(data, { + service_id :: binary(), + device_uuid :: binary(), + route_key :: binary(), + metric :: binary() +}). + +-record(event, { + service_id :: binary(), + event_type :: integer(), + params :: binary() +}). + +-record(task_event_stream, { + task_id :: integer(), + type :: binary(), + stream :: binary() +}). \ No newline at end of file diff --git a/apps/iot/include/message_pb.hrl b/apps/iot/include/message_pb.hrl deleted file mode 100644 index 007b324..0000000 --- a/apps/iot/include/message_pb.hrl +++ /dev/null @@ -1,133 +0,0 @@ -%% -*- coding: utf-8 -*- -%% Automatically generated, do not edit -%% Generated by gpb_compile version 4.21.1 - --ifndef(message_pb). --define(message_pb, true). - --define(message_pb_gpb_version, "4.21.1"). - - --ifndef('AUTH_REQUEST_PB_H'). --define('AUTH_REQUEST_PB_H', true). --record(auth_request, - {uuid = <<>> :: unicode:chardata() | undefined, % = 1, optional - username = <<>> :: unicode:chardata() | undefined, % = 2, optional - salt = <<>> :: unicode:chardata() | undefined, % = 4, optional - token = <<>> :: unicode:chardata() | undefined, % = 5, optional - timestamp = 0 :: non_neg_integer() | undefined % = 6, optional, 32 bits - }). --endif. - --ifndef('AUTH_REPLY_PB_H'). --define('AUTH_REPLY_PB_H', true). --record(auth_reply, - {code = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits - message = <<>> :: unicode:chardata() | undefined % = 2, optional - }). --endif. - --ifndef('PUB_PB_H'). --define('PUB_PB_H', true). --record(pub, - {topic = <<>> :: unicode:chardata() | undefined, % = 1, optional - content = <<>> :: iodata() | undefined % = 2, optional - }). --endif. - --ifndef('COMMAND_PB_H'). --define('COMMAND_PB_H', true). --record(command, - {command_type = <<>> :: unicode:chardata() | undefined, % = 1, optional - command = <<>> :: iodata() | undefined % = 2, optional - }). --endif. - --ifndef('RPC_DEPLOY_PB_H'). --define('RPC_DEPLOY_PB_H', true). --record(rpc_deploy, - {packet_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits - task_id = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits - config = <<>> :: unicode:chardata() | undefined % = 3, optional - }). --endif. - --ifndef('RPC_START_CONTAINER_PB_H'). --define('RPC_START_CONTAINER_PB_H', true). --record(rpc_start_container, - {packet_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits - container_name = <<>> :: unicode:chardata() | undefined % = 2, optional - }). --endif. - --ifndef('RPC_STOP_CONTAINER_PB_H'). --define('RPC_STOP_CONTAINER_PB_H', true). --record(rpc_stop_container, - {packet_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits - container_name = <<>> :: unicode:chardata() | undefined % = 2, optional - }). --endif. - --ifndef('RPC_CONFIG_CONTAINER_PB_H'). --define('RPC_CONFIG_CONTAINER_PB_H', true). --record(rpc_config_container, - {packet_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits - container_name = <<>> :: unicode:chardata() | undefined, % = 2, optional - config = <<>> :: iodata() | undefined % = 3, optional - }). --endif. - --ifndef('FETCH_TASK_LOG_PB_H'). --define('FETCH_TASK_LOG_PB_H', true). --record(fetch_task_log, - {task_id = 0 :: non_neg_integer() | undefined % = 1, optional, 32 bits - }). --endif. - --ifndef('CONTAINER_CONFIG_PB_H'). --define('CONTAINER_CONFIG_PB_H', true). --record(container_config, - {container_name = <<>> :: unicode:chardata() | undefined, % = 1, optional - config = <<>> :: iodata() | undefined % = 2, optional - }). --endif. - --ifndef('DATA_PB_H'). --define('DATA_PB_H', true). --record(data, - {service_id = <<>> :: unicode:chardata() | undefined, % = 1, optional - device_uuid = <<>> :: unicode:chardata() | undefined, % = 2, optional - route_key = <<>> :: unicode:chardata() | undefined, % = 3, optional - metric = <<>> :: iodata() | undefined % = 4, optional - }). --endif. - --ifndef('EVENT_PB_H'). --define('EVENT_PB_H', true). --record(event, - {service_id = <<>> :: unicode:chardata() | undefined, % = 1, optional - event_type = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits - params = <<>> :: unicode:chardata() | undefined % = 3, optional - }). --endif. - --ifndef('PING_PB_H'). --define('PING_PB_H', true). --record(ping, - {adcode = <<>> :: unicode:chardata() | undefined, % = 1, optional - boot_time = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits - province = <<>> :: unicode:chardata() | undefined, % = 3, optional - city = <<>> :: unicode:chardata() | undefined, % = 4, optional - efka_version = <<>> :: unicode:chardata() | undefined, % = 5, optional - kernel_arch = <<>> :: unicode:chardata() | undefined, % = 6, optional - ips = [] :: [unicode:chardata()] | undefined, % = 7, repeated - cpu_core = 0 :: non_neg_integer() | undefined, % = 8, optional, 32 bits - cpu_load = 0 :: non_neg_integer() | undefined, % = 9, optional, 32 bits - cpu_temperature = 0.0 :: float() | integer() | infinity | '-infinity' | nan | undefined, % = 10, optional - disk = [] :: [integer()] | undefined, % = 11, repeated, 32 bits - memory = [] :: [integer()] | undefined, % = 12, repeated, 32 bits - interfaces = <<>> :: unicode:chardata() | undefined % = 13, optional - }). --endif. - --endif. diff --git a/apps/iot/src/database/ai_event_logs_bo.erl b/apps/iot/src/database/ai_event_logs_bo.erl deleted file mode 100644 index b9a4349..0000000 --- a/apps/iot/src/database/ai_event_logs_bo.erl +++ /dev/null @@ -1,30 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(ai_event_logs_bo). --author("aresei"). --include("iot.hrl"). - --export([insert/6]). - -%% API - --spec insert(HostUUID :: binary(), DeviceUUID :: binary(), SceneId :: integer(), MicroId :: integer(), EventType :: integer(), Content :: binary()) -> - ok | {ok, InsertId :: integer()} | {error, Reason :: any()}. -insert(HostUUID, DeviceUUID, SceneId, MicroId, EventType, Content) - when is_integer(EventType), is_binary(HostUUID), is_binary(DeviceUUID), is_integer(SceneId), is_integer(MicroId), is_binary(Content) -> - - mysql_pool:insert(mysql_iot, <<"ai_event_logs">>, #{ - <<"event_type">> => EventType, - <<"host_uuid">> => HostUUID, - <<"device_uuid">> => DeviceUUID, - <<"scene_id">> => SceneId, - <<"micro_id">> => MicroId, - <<"content">> => Content, - <<"created_at">> => calendar:local_time() - }, true). \ No newline at end of file diff --git a/apps/iot/src/database/device_bo.erl b/apps/iot/src/database/device_bo.erl deleted file mode 100644 index b877a6c..0000000 --- a/apps/iot/src/database/device_bo.erl +++ /dev/null @@ -1,43 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(device_bo). --author("aresei"). --include("iot.hrl"). - -%% API --export([get_all_devices/0, get_host_devices/1, get_device_by_uuid/1, change_status/2]). - --spec get_all_devices() -> {ok, Devices :: [map()]} | {error, Reason :: any()}. -get_all_devices() -> - mysql_pool:get_all(mysql_iot, <<"SELECT * FROM device WHERE device_uuid != ''">>). - --spec get_host_devices(HostId :: integer()) -> {ok, Devices :: [map()]} | {error, Reason::any()}. -get_host_devices(HostId) when is_integer(HostId) -> - mysql_pool:get_all(mysql_iot, <<"SELECT device_uuid FROM device WHERE host_id = ? AND device_uuid != ''">>, [HostId]). - --spec get_device_by_uuid(DeviceUUID :: binary()) -> {ok, DeviceInfo :: map()} | undefined. -get_device_by_uuid(DeviceUUID) when is_binary(DeviceUUID) -> - mysql_pool:get_row(mysql_iot, <<"SELECT * FROM device WHERE device_uuid = ? LIMIT 1">>, [DeviceUUID]). - -%% 修改主机的状态 --spec change_status(DeviceUUID :: binary(), Status :: integer()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. -change_status(DeviceUUID, NStatus) when is_binary(DeviceUUID), is_integer(NStatus) -> - change_status0(DeviceUUID, NStatus). -change_status0(DeviceUUID, ?DEVICE_ONLINE) when is_binary(DeviceUUID) -> - Timestamp = calendar:local_time(), - case mysql_pool:get_row(mysql_iot, <<"SELECT status FROM device WHERE device_uuid = ? LIMIT 1">>, [DeviceUUID]) of - {ok, #{<<"status">> := -1}} -> - mysql_pool:update_by(mysql_iot, <<"UPDATE device SET status = ?, access_at = ?, updated_at = ? WHERE device_uuid = ? LIMIT 1">>, [?DEVICE_ONLINE, Timestamp, Timestamp, DeviceUUID]); - {ok, _} -> - mysql_pool:update_by(mysql_iot, <<"UPDATE device SET status = ?, updated_at = ? WHERE device_uuid = ? LIMIT 1">>, [?DEVICE_ONLINE, Timestamp, DeviceUUID]); - undefined -> - {error, <<"device not found">>} - end; -change_status0(DeviceUUID, ?DEVICE_OFFLINE) when is_binary(DeviceUUID) -> - mysql_pool:update_by(mysql_iot, <<"UPDATE device SET status = ? WHERE device_uuid = ? LIMIT 1">>, [?DEVICE_OFFLINE, DeviceUUID]). \ No newline at end of file diff --git a/apps/iot/src/database/endpoint_bo.erl b/apps/iot/src/database/endpoint_bo.erl deleted file mode 100644 index 2688916..0000000 --- a/apps/iot/src/database/endpoint_bo.erl +++ /dev/null @@ -1,97 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(endpoint_bo). --author("aresei"). --include("endpoint.hrl"). - -%% API --export([get_all_endpoints/0, get_endpoint/1]). --export([endpoint_record/1]). - --spec get_all_endpoints() -> [Endpoint :: map()]. -get_all_endpoints() -> - case mysql_pool:get_all(mysql_iot, <<"SELECT * FROM endpoint where status = 1">>) of - {ok, Endpoints} -> - Endpoints; - {error, _} -> - [] - end. - --spec get_endpoint(Id :: integer()) -> undefined | {ok, EndpointInfo :: map()}. -get_endpoint(Id) when is_integer(Id) -> - mysql_pool:get_row(mysql_iot, <<"SELECT * FROM endpoint WHERE id = ? and status = 1 LIMIT 1">>, [Id]). - --spec endpoint_record(EndpointInfo :: #{}) -> error | {ok, Endpoint :: #endpoint{}}. -endpoint_record(#{<<"id">> := Id, <<"name">> := Name, <<"title">> := Title, <<"type">> := Type, <<"config_json">> := ConfigJson, - <<"status">> := Status, <<"updated_at">> := UpdatedAt, <<"created_at">> := CreatedAt}) -> - try - Config = parse_config(Type, catch jiffy:decode(ConfigJson, [return_maps])), - {ok, #endpoint { - id = Id, - name = Name, - title = Title, - config = Config, - status = Status, - updated_at = UpdatedAt, - created_at = CreatedAt - }} - catch throw:_ -> - error - end. - -parse_config(<<"mqtt">>, #{<<"host">> := Host, <<"port">> := Port, <<"client_id">> := ClientId, <<"username">> := Username, <<"password">> := Password, <<"topic">> := Topic, <<"qos">> := Qos}) -> - #mqtt_endpoint{ - host = Host, - port = Port, - client_id = ClientId, - username = Username, - password = Password, - topic = Topic, - qos = Qos - }; -parse_config(<<"http">>, #{<<"url">> := Url, <<"pool_size">> := PoolSize}) -> - #http_endpoint{ - url = Url, - pool_size = PoolSize - }; -parse_config(<<"kafka">>, #{<<"sasl_config">> := #{<<"username">> := Username, <<"password">> := Password, <<"mechanism">> := Mechanism0}, <<"bootstrap_servers">> := BootstrapServers, <<"topic">> := Topic}) -> - Mechanism = case Mechanism0 of - <<"sha_256">> -> - scram_sha_256; - <<"sha_512">> -> - scram_sha_512; - <<"plain">> -> - plain; - _ -> - plain - end, - - #kafka_endpoint{ - sasl_config = {Mechanism, Username, Password}, - bootstrap_servers = parse_bootstrap_servers(BootstrapServers), - topic = Topic - }; -parse_config(<<"kafka">>, #{<<"bootstrap_servers">> := BootstrapServers, <<"topic">> := Topic}) -> - #kafka_endpoint{ - sasl_config = undefined, - bootstrap_servers = parse_bootstrap_servers(BootstrapServers), - topic = Topic - }; -parse_config(_, _) -> - throw(invalid_config). - -parse_bootstrap_servers(BootstrapServers) when is_list(BootstrapServers) -> - lists:filtermap(fun(S) -> - case binary:split(S, <<":">>) of - [Host0, Port0] -> - {true, {binary_to_list(Host0), binary_to_integer(Port0)}}; - _ -> - false - end - end, BootstrapServers). \ No newline at end of file diff --git a/apps/iot/src/database/event_logs_bo.erl b/apps/iot/src/database/event_logs_bo.erl deleted file mode 100644 index 87f98c8..0000000 --- a/apps/iot/src/database/event_logs_bo.erl +++ /dev/null @@ -1,25 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(event_logs_bo). --author("aresei"). --include("iot.hrl"). - --export([insert/3]). - -%% API - --spec insert(EventType :: integer(), AssocUUID :: binary(), Status :: integer()) -> - {ok, InsertId :: integer()} | {error, Reason :: any()}. -insert(EventType, AssocUUID, Status) when is_integer(EventType), is_binary(AssocUUID), is_integer(Status) -> - mysql_pool:insert(mysql_iot, <<"event_logs">>, #{ - <<"event_type">> => EventType, - <<"assoc_uuid">> => AssocUUID, - <<"status">> => Status, - <<"created_at">> => calendar:local_time() - }, true). \ No newline at end of file diff --git a/apps/iot/src/database/host_bo.erl b/apps/iot/src/database/host_bo.erl deleted file mode 100644 index f2e5087..0000000 --- a/apps/iot/src/database/host_bo.erl +++ /dev/null @@ -1,49 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(host_bo). --author("aresei"). --include("iot.hrl"). - -%% API --export([get_all_hosts/0, change_status/2, get_host_by_uuid/1, get_host_by_id/1]). - --spec get_all_hosts() -> UUIDList :: [binary()]. -get_all_hosts() -> - case mysql_pool:get_all(mysql_iot, <<"SELECT uuid FROM host where uuid != '' limit 10">>) of - {ok, Hosts} -> - lists:map(fun(#{<<"uuid">> := UUID}) -> UUID end, Hosts); - {error, _} -> - [] - end. - --spec get_host_by_uuid(UUID :: binary()) -> undefined | {ok, HostInfo :: map()}. -get_host_by_uuid(UUID) when is_binary(UUID) -> - mysql_pool:get_row(mysql_iot, <<"SELECT * FROM host WHERE uuid = ? LIMIT 1">>, [UUID]). - --spec get_host_by_id(HostId :: integer()) -> undefined | {ok, HostInfo :: map()}. -get_host_by_id(HostId) when is_integer(HostId) -> - mysql_pool:get_row(mysql_iot, <<"SELECT * FROM host WHERE id = ? LIMIT 1">>, [HostId]). - -%% 修改主机的状态 --spec change_status(UUID :: binary(), Status :: integer()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. -change_status(UUID, NStatus) when is_binary(UUID), is_integer(NStatus) -> - change_status0(UUID, NStatus). -change_status0(UUID, ?HOST_ONLINE) when is_binary(UUID) -> - Timestamp = calendar:local_time(), - case mysql_pool:get_row(mysql_iot, <<"SELECT status FROM host WHERE uuid = ? LIMIT 1">>, [UUID]) of - %% 第一次更新激活 - {ok, #{<<"status">> := -1}} -> - mysql_pool:update_by(mysql_iot, <<"UPDATE host SET status = ?, access_at = ?, updated_at = ? WHERE uuid = ? LIMIT 1">>, [?HOST_ONLINE, Timestamp, Timestamp, UUID]); - {ok, _} -> - mysql_pool:update_by(mysql_iot, <<"UPDATE host SET status = ?, updated_at = ? WHERE uuid = ? LIMIT 1">>, [?HOST_ONLINE, Timestamp, UUID]); - undefined -> - {error, <<"host not found">>} - end; -change_status0(UUID, ?HOST_OFFLINE) when is_binary(UUID) -> - mysql_pool:update_by(mysql_iot, <<"UPDATE host SET status = ? WHERE uuid = ? LIMIT 1">>, [?HOST_OFFLINE, UUID]). \ No newline at end of file diff --git a/apps/iot/src/database/micro_inform_log.erl b/apps/iot/src/database/micro_inform_log.erl deleted file mode 100644 index c5128fd..0000000 --- a/apps/iot/src/database/micro_inform_log.erl +++ /dev/null @@ -1,17 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(micro_inform_log). --author("aresei"). --include("iot.hrl"). - -%% API --export([insert/1]). - -insert(Fields) when is_map(Fields) -> - mysql_pool:insert(mysql_iot, <<"micro_inform_log">>, Fields, true). \ No newline at end of file diff --git a/apps/iot/src/database/micro_service_bo.erl b/apps/iot/src/database/micro_service_bo.erl deleted file mode 100644 index 03a2b86..0000000 --- a/apps/iot/src/database/micro_service_bo.erl +++ /dev/null @@ -1,23 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(micro_service_bo). --author("aresei"). --export([get_service_config/1]). - -%% API - -%% TODO --spec get_service_config(ServiceId :: binary()) -> {ok, ConfigJson :: binary()} | error. -get_service_config(ServiceId) when is_binary(ServiceId) -> - case mysql_pool:get_row(mysql_iot, <<"SELECT * FROM micro_service WHERE id = ? LIMIT 1">>, [ServiceId]) of - undefined -> - error; - {ok, #{<<"config">> := Config}} -> - {ok, Config} - end. \ No newline at end of file diff --git a/apps/iot/src/database/micro_set_bo.erl b/apps/iot/src/database/micro_set_bo.erl deleted file mode 100644 index 80e30ee..0000000 --- a/apps/iot/src/database/micro_set_bo.erl +++ /dev/null @@ -1,19 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(micro_set_bo). --author("aresei"). --include("iot.hrl"). - -%% API --export([change_status/4]). - -%% 修改主机的状态 --spec change_status(HostId :: integer(), SceneId :: integer(), MircoId :: integer(), Status :: integer()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. -change_status(HostId, SceneId, MircoId, Status) when is_integer(HostId), is_integer(SceneId), is_integer(MircoId), is_integer(Status) -> - mysql_pool:update_by(mysql_iot, <<"UPDATE micro_set SET status = ? WHERE host_id = ? AND scene_id = ? AND micro_id = ? LIMIT 1">>, [Status, HostId, SceneId, MircoId]). \ No newline at end of file diff --git a/apps/iot/src/database/task_logs_bo.erl b/apps/iot/src/database/task_logs_bo.erl deleted file mode 100644 index 4d2b25a..0000000 --- a/apps/iot/src/database/task_logs_bo.erl +++ /dev/null @@ -1,19 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 16. 5月 2023 12:48 -%%%------------------------------------------------------------------- --module(task_logs_bo). --author("aresei"). --include("iot.hrl"). - -%% API --export([change_status/2]). - -%% 修改主机的状态 --spec change_status(TaskId :: integer(), Status :: integer()) -> {ok, AffectedRow :: integer()} | {error, Reason :: any()}. -change_status(TaskId, Status) when is_integer(TaskId), is_integer(Status) -> - mysql_pool:update_by(mysql_iot, <<"UPDATE task_logs SET status = ? WHERE id = ? LIMIT 1">>, [Status, TaskId]). \ No newline at end of file diff --git a/apps/iot/src/endpoint/endpoint.erl b/apps/iot/src/endpoint/endpoint.erl index 250f013..89d1a1e 100644 --- a/apps/iot/src/endpoint/endpoint.erl +++ b/apps/iot/src/endpoint/endpoint.erl @@ -13,25 +13,23 @@ %% API -export([start_link/1]). -export([get_name/1, get_pid/1, forward/3, reload/2, clean_up/1]). --export([get_alias_pid/1]). +-export([get_alias_pid/1, is_support/1, get_protocol/1]). +-export([endpoint_record/1]). %%%=================================================================== %%% API %%%=================================================================== -spec start_link(Endpoint :: #endpoint{}) -> {'ok', pid()} | 'ignore' | {'error', term()}. -start_link(Endpoint = #endpoint{id = Id, name = Name, config = #http_endpoint{}}) -> +start_link(Endpoint = #endpoint{id = Id, config = #http_endpoint{}}) -> LocalName = get_name(Id), - AliasName = get_alias_name(Name), - endpoint_http:start_link(LocalName, AliasName, Endpoint); -start_link(Endpoint = #endpoint{id = Id, name = Name, config = #mqtt_endpoint{}}) -> + endpoint_http:start_link(LocalName, Endpoint); +start_link(Endpoint = #endpoint{id = Id, config = #mqtt_endpoint{}}) -> LocalName = get_name(Id), - AliasName = get_alias_name(Name), - endpoint_mqtt:start_link(LocalName, AliasName, Endpoint); -start_link(Endpoint = #endpoint{id = Id, name = Name, config = #kafka_endpoint{}}) -> + endpoint_mqtt:start_link(LocalName, Endpoint); +start_link(Endpoint = #endpoint{id = Id, config = #kafka_endpoint{}}) -> LocalName = get_name(Id), - AliasName = get_alias_name(Name), - endpoint_kafka:start_link(LocalName, AliasName, Endpoint). + endpoint_kafka:start_link(LocalName, Endpoint). -spec get_name(Id :: integer()) -> atom(). get_name(Id) when is_integer(Id) -> @@ -58,4 +56,88 @@ reload(Pid, NEndpoint = #endpoint{}) when is_pid(Pid) -> -spec clean_up(Pid :: pid()) -> ok. clean_up(Pid) when is_pid(Pid) -> - gen_server:call(Pid, clean_up, 5000). \ No newline at end of file + gen_server:call(Pid, clean_up, 5000). + +-spec get_protocol(Endpoint :: #endpoint{}) -> atom(). +get_protocol(#endpoint{config = #http_endpoint{}}) -> + http; +get_protocol(#endpoint{config = #mqtt_endpoint{}}) -> + mqtt; +get_protocol(#endpoint{config = #kafka_endpoint{}}) -> + kafka. + +-spec is_support(Protocol :: atom()) -> boolean(). +is_support(Protocol) when is_atom(Protocol) -> + {ok, Props} = application:get_env(iot, endpoints), + SupportProtocols = proplists:get_value(support_protocols, Props, []), + lists:member(Protocol, SupportProtocols). + +-spec endpoint_record(EndpointInfo :: #{}) -> error | {ok, Endpoint :: #endpoint{}}. +endpoint_record(#{<<"id">> := Id, <<"matcher">> := Matcher, <<"title">> := Title, <<"type">> := Type, <<"config">> := ConfigJson, + <<"status">> := Status, <<"updated_at">> := UpdatedAt, <<"created_at">> := CreatedAt}) -> + try + Config = parse_config(Type, ConfigJson), + {ok, #endpoint { + id = Id, + matcher = Matcher, + title = Title, + config = Config, + status = Status, + updated_at = UpdatedAt, + created_at = CreatedAt + }} + catch throw:_ -> + error + end. + +parse_config(<<"mqtt">>, #{<<"host">> := Host, <<"port">> := Port0, <<"client_id">> := ClientId, <<"username">> := Username, <<"password">> := Password, <<"topic">> := Topic, <<"qos">> := Qos}) -> + Port = if is_binary(Port0) -> binary_to_integer(Port0); is_integer(Port0) -> Port0 end, + #mqtt_endpoint{ + host = Host, + port = Port, + client_id = ClientId, + username = Username, + password = Password, + topic = Topic, + qos = Qos + }; +parse_config(<<"http">>, #{<<"url">> := Url, <<"pool_size">> := PoolSize}) -> + #http_endpoint{ + url = Url, + pool_size = PoolSize + }; +parse_config(<<"kafka">>, #{<<"sasl_config">> := #{<<"username">> := Username, <<"password">> := Password, <<"mechanism">> := Mechanism0}, <<"bootstrap_servers">> := BootstrapServers, <<"topic">> := Topic}) -> + Mechanism = case Mechanism0 of + <<"sha_256">> -> + scram_sha_256; + <<"sha_512">> -> + scram_sha_512; + <<"plain">> -> + plain; + _ -> + plain + end, + + #kafka_endpoint{ + sasl_config = {Mechanism, Username, Password}, + bootstrap_servers = parse_bootstrap_servers(BootstrapServers), + topic = Topic + }; +parse_config(<<"kafka">>, #{<<"bootstrap_servers">> := BootstrapServers, <<"topic">> := Topic}) -> + #kafka_endpoint{ + sasl_config = undefined, + bootstrap_servers = parse_bootstrap_servers(BootstrapServers), + topic = Topic + }; +parse_config(_, _) -> + throw(invalid_config). + +parse_bootstrap_servers(BootstrapServers) when is_list(BootstrapServers) -> + lists:filtermap(fun(S) -> + case binary:split(S, <<":">>) of + [Host0, Port0] -> + {true, {binary_to_list(Host0), binary_to_integer(Port0)}}; + _ -> + false + end + end, BootstrapServers). \ No newline at end of file diff --git a/apps/iot/src/endpoint/endpoint_http.erl b/apps/iot/src/endpoint/endpoint_http.erl index ecfd4fc..585af1e 100644 --- a/apps/iot/src/endpoint/endpoint_http.erl +++ b/apps/iot/src/endpoint/endpoint_http.erl @@ -13,7 +13,7 @@ -behaviour(gen_server). %% API --export([start_link/3]). +-export([start_link/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -30,10 +30,10 @@ %%%=================================================================== %% @doc Spawns the server and registers the local name (unique) --spec(start_link(LocalName :: atom(), AliasName :: atom(), Endpoint :: #endpoint{}) -> +-spec(start_link(LocalName :: atom(), Endpoint :: #endpoint{}) -> {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). -start_link(LocalName, AliasName, Endpoint = #endpoint{config = #http_endpoint{}}) when is_atom(LocalName), is_atom(AliasName) -> - gen_server:start_link({local, LocalName}, ?MODULE, [AliasName, Endpoint], []). +start_link(LocalName, Endpoint = #endpoint{config = #http_endpoint{}}) when is_atom(LocalName) -> + gen_server:start_link({local, LocalName}, ?MODULE, [Endpoint], []). %%%=================================================================== %%% gen_server callbacks @@ -44,9 +44,9 @@ start_link(LocalName, AliasName, Endpoint = #endpoint{config = #http_endpoint{}} -spec(init(Args :: term()) -> {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {stop, Reason :: term()} | ignore). -init([AliasName, Endpoint]) -> +init([Endpoint = #endpoint{matcher = Matcher}]) -> + endpoint_subscription:subscribe(Matcher, self()), Buffer = endpoint_buffer:new(Endpoint, 10), - true = gproc:reg({n, l, AliasName}), {ok, #state{endpoint = Endpoint, buffer = Buffer}}. %% @private diff --git a/apps/iot/src/endpoint/endpoint_kafka.erl b/apps/iot/src/endpoint/endpoint_kafka.erl index ccd9e99..7c16a8e 100644 --- a/apps/iot/src/endpoint/endpoint_kafka.erl +++ b/apps/iot/src/endpoint/endpoint_kafka.erl @@ -13,7 +13,7 @@ -behaviour(gen_server). %% API --export([start_link/3]). +-export([start_link/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -39,8 +39,8 @@ %% @doc Creates a gen_statem process which calls Module:init/1 to %% initialize. To ensure a synchronized start-up procedure, this %% function does not return until Module:init/1 has returned. -start_link(LocalName, AliasName, Endpoint = #endpoint{}) when is_atom(LocalName), is_atom(AliasName) -> - gen_server:start_link({local, LocalName}, ?MODULE, [AliasName, Endpoint], []). +start_link(LocalName, Endpoint = #endpoint{}) when is_atom(LocalName) -> + gen_server:start_link({local, LocalName}, ?MODULE, [Endpoint], []). %%%=================================================================== %%% gen_statem callbacks @@ -50,10 +50,10 @@ start_link(LocalName, AliasName, Endpoint = #endpoint{}) when is_atom(LocalName) %% @doc Whenever a gen_statem is started using gen_statem:start/[3,4] or %% gen_statem:start_link/[3,4], this function is called by the new %% process to initialize. -init([AliasName, Endpoint = #endpoint{id = Id}]) -> - erlang:process_flag(trap_exit, true), - true = gproc:reg({n, l, AliasName}), +init([Endpoint = #endpoint{id = Id, matcher = Matcher}]) -> + endpoint_subscription:subscribe(Matcher, self()), + erlang:process_flag(trap_exit, true), %% 创建转发器, 避免阻塞当前进程的创建,因此采用了延时初始化的机制 erlang:start_timer(0, self(), connect), %% 初始化存储 @@ -108,13 +108,19 @@ handle_info({timeout, _, connect}, State = #state{buffer = Buffer, status = ?DIS BaseConfig end, - case brod:start_link_client(BootstrapServers, ClientId, ClientConfig) of + case catch brod:start_link_client(BootstrapServers, ClientId, ClientConfig) of {ok, ClientPid} -> - ok = brod:start_producer(ClientId, Topic, _ProducerConfig = []), - NBuffer = endpoint_buffer:trigger_next(Buffer), - {noreply, State#state{buffer = NBuffer, client_pid = ClientPid, status = ?CONNECTED}}; - {error, Reason} -> - lager:debug("[endpoint_kafka] start_client: ~p, get error: ~p", [ClientId, Reason]), + case brod:start_producer(ClientId, Topic, _ProducerConfig = []) of + ok -> + NBuffer = endpoint_buffer:trigger_next(Buffer), + {noreply, State#state{buffer = NBuffer, client_pid = ClientPid, status = ?CONNECTED}}; + {error, Reason} -> + lager:debug("[endpoint_kafka] start_producer: ~p, get error: ~p", [ClientId, Reason]), + retry_connect(), + {noreply, State#state{status = ?DISCONNECTED, client_pid = undefined}} + end; + Error -> + lager:debug("[endpoint_kafka] start_client: ~p, get error: ~p", [ClientId, Error]), retry_connect(), {noreply, State#state{status = ?DISCONNECTED, client_pid = undefined}} end; @@ -174,12 +180,4 @@ code_change(_OldVsn, State = #state{}, _Extra) -> %%%=================================================================== retry_connect() -> - erlang:start_timer(?RETRY_INTERVAL, self(), connect). - -check_produce_result(ok) -> - true; -check_produce_result({ok, _}) -> - true; -check_produce_result({ok, _}) -> - false. - + erlang:start_timer(?RETRY_INTERVAL, self(), connect). \ No newline at end of file diff --git a/apps/iot/src/endpoint/endpoint_mqtt.erl b/apps/iot/src/endpoint/endpoint_mqtt.erl index 59dfc43..87eabec 100644 --- a/apps/iot/src/endpoint/endpoint_mqtt.erl +++ b/apps/iot/src/endpoint/endpoint_mqtt.erl @@ -13,7 +13,7 @@ -behaviour(gen_server). %% API --export([start_link/3]). +-export([start_link/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -41,8 +41,8 @@ %% @doc Creates a gen_statem process which calls Module:init/1 to %% initialize. To ensure a synchronized start-up procedure, this %% function does not return until Module:init/1 has returned. -start_link(LocalName, AliasName, Endpoint = #endpoint{}) when is_atom(LocalName), is_atom(AliasName) -> - gen_server:start_link({local, LocalName}, ?MODULE, [AliasName, Endpoint], []). +start_link(LocalName, Endpoint = #endpoint{}) when is_atom(LocalName) -> + gen_server:start_link({local, LocalName}, ?MODULE, [Endpoint], []). %%%=================================================================== %%% gen_statem callbacks @@ -52,9 +52,10 @@ start_link(LocalName, AliasName, Endpoint = #endpoint{}) when is_atom(LocalName) %% @doc Whenever a gen_statem is started using gen_statem:start/[3,4] or %% gen_statem:start_link/[3,4], this function is called by the new %% process to initialize. -init([AliasName, Endpoint]) -> - erlang:process_flag(trap_exit, true), - true = gproc:reg({n, l, AliasName}), +init([Endpoint = #endpoint{matcher = Matcher}]) -> + % erlang:process_flag(trap_exit, true), + endpoint_subscription:subscribe(Matcher, self()), + %% 创建转发器, 避免阻塞当前进程的创建,因此采用了延时初始化的机制 erlang:start_timer(0, self(), create_postman), %% 初始化存储 @@ -94,7 +95,7 @@ handle_cast({forward, ServiceId, Metric}, State = #state{buffer = Buffer}) -> {stop, Reason :: term(), NewState :: #state{}}). handle_info({timeout, _, create_postman}, State = #state{buffer = Buffer, status = ?DISCONNECTED, endpoint = #endpoint{title = Title, config = #mqtt_endpoint{host = Host, port = Port, username = Username, password = Password, client_id = ClientId}}}) -> - lager:debug("[endpoint_mqtt] endpoint: ~p, create postman", [Title]), + lager:debug("[endpoint_mqtt] endpoint: ~ts, create postman", [Title]), Opts = [ {owner, self()}, {clientid, ClientId}, @@ -112,7 +113,7 @@ handle_info({timeout, _, create_postman}, State = #state{buffer = Buffer, status {ok, ConnPid} = emqtt:start_link(Opts), lager:debug("[endpoint_mqtt] start connect, options: ~p", [Opts]), - case emqtt:connect(ConnPid, 5000) of + case catch emqtt:connect(ConnPid, 5000) of {ok, _} -> lager:debug("[endpoint_mqtt] connect success, pid: ~p", [ConnPid]), NBuffer = endpoint_buffer:trigger_n(Buffer), @@ -120,6 +121,10 @@ handle_info({timeout, _, create_postman}, State = #state{buffer = Buffer, status {error, Reason} -> lager:warning("[endpoint_mqtt] connect get error: ~p", [Reason]), erlang:start_timer(5000, self(), create_postman), + {noreply, State}; + Error -> + lager:warning("[endpoint_mqtt] connect get error: ~p", [Error]), + erlang:start_timer(5000, self(), create_postman), {noreply, State} end; diff --git a/apps/iot/src/endpoint/endpoint_subscription.erl b/apps/iot/src/endpoint/endpoint_subscription.erl new file mode 100644 index 0000000..d9d0f05 --- /dev/null +++ b/apps/iot/src/endpoint/endpoint_subscription.erl @@ -0,0 +1,200 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 07. 11月 2025 16:27 +%%%------------------------------------------------------------------- +-module(endpoint_subscription). +-author("anlicheng"). + +-behaviour(gen_server). + +%% API +-export([start_link/0]). +-export([subscribe/2, publish/3]). +-export([match_components/2, is_valid_components/1, of_components/1]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). + +-define(SERVER, ?MODULE). + +%% 定义订阅者 +-record(subscriber, { + topic :: binary(), + subscriber_pid :: pid(), + components = [], + %% 优先级 + %% 1. 完全匹配的topic优先级别最高 + %% 2. 带 * 的订阅 + %% 3. 带 + 的订阅 + order :: integer() +}). + +-record(state, { + subscribers = [] +}). + +%%%=================================================================== +%%% API +%%%=================================================================== + +-spec subscribe(Topic :: binary(), SubscriberPid :: pid()) -> ok | {error, Reason :: binary()}. +subscribe(Topic, SubscriberPid) when is_binary(Topic), is_pid(SubscriberPid) -> + gen_server:call(?SERVER, {subscribe, Topic, SubscriberPid}). + +-spec publish(RouteKey :: binary(), ServiceId :: binary(), Content :: binary()) -> no_return(). +publish(RouteKey, ServiceId, Content) when is_binary(RouteKey), is_binary(Content) -> + gen_server:cast(?SERVER, {publish, RouteKey, ServiceId, Content}). + +%% @doc Spawns the server and registers the local name (unique) +-spec(start_link() -> + {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). +start_link() -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== + +%% @private +%% @doc Initializes the server +-spec(init(Args :: term()) -> + {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | + {stop, Reason :: term()} | ignore). +init([]) -> + {ok, #state{}}. + +%% @private +%% @doc Handling call messages +-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()}, + State :: #state{}) -> + {reply, Reply :: term(), NewState :: #state{}} | + {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} | + {noreply, NewState :: #state{}} | + {noreply, NewState :: #state{}, timeout() | hibernate} | + {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} | + {stop, Reason :: term(), NewState :: #state{}}). +%% 同一个SubscriberPid只能订阅同一个topic一次 +handle_call({subscribe, Topic, SubscriberPid}, _From, State = #state{subscribers = Subscribers}) -> + Components = of_components(Topic), + case is_valid_components(Components) of + true -> + Sub = #subscriber{topic = Topic, subscriber_pid = SubscriberPid, components = Components, order = order_num(Components)}, + %% 建立到SubscriberPid的monitor,进程退出需要清理订阅 + erlang:monitor(process, SubscriberPid), + + {reply, ok, State#state{subscribers = Subscribers ++ [Sub]}}; + false -> + {reply, {error, <<"invalid topic name">>}, State} + end. + +%% @private +%% @doc Handling cast messages +-spec(handle_cast(Request :: term(), State :: #state{}) -> + {noreply, NewState :: #state{}} | + {noreply, NewState :: #state{}, timeout() | hibernate} | + {stop, Reason :: term(), NewState :: #state{}}). +%% 发布消息 +handle_cast({publish, RouteKey, ServiceId, Metric}, State = #state{subscribers = Subscribers}) -> + MatchedSubscribers = match_subscribers(Subscribers, RouteKey), + lists:foreach(fun(#subscriber{subscriber_pid = SubscriberPid}) -> + endpoint:forward(SubscriberPid, ServiceId, Metric) + end, MatchedSubscribers), + lager:debug("[efka_subscription] route_key: ~p, metric: ~p, match subscribers: ~p", [RouteKey, Metric, MatchedSubscribers]), + {noreply, State}. + +%% @private +%% @doc Handling all non call/cast messages +-spec(handle_info(Info :: timeout() | term(), State :: #state{}) -> + {noreply, NewState :: #state{}} | + {noreply, NewState :: #state{}, timeout() | hibernate} | + {stop, Reason :: term(), NewState :: #state{}}). +handle_info({'DOWN', _Ref, process, SubscriberPid, Reason}, State = #state{subscribers = Subscribers}) -> + lager:debug("[efka_subscription] subscriber: ~p, down with reason: ~p", [SubscriberPid, Reason]), + NSubscribers = lists:filter(fun(#subscriber{subscriber_pid = Pid0}) -> SubscriberPid /= Pid0 end, Subscribers), + {noreply, State#state{subscribers = NSubscribers}}; + +handle_info(Info, State = #state{}) -> + lager:debug("[efka_subscription] get unknown info: ~p", [Info]), + {noreply, State}. + +%% @private +%% @doc This function is called by a gen_server when it is about to +%% terminate. It should be the opposite of Module:init/1 and do any +%% necessary cleaning up. When it returns, the gen_server terminates +%% with Reason. The return value is ignored. +-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), + State :: #state{}) -> term()). +terminate(_Reason, _State = #state{}) -> + ok. + +%% @private +%% @doc Convert process state when code is changed +-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{}, + Extra :: term()) -> + {ok, NewState :: #state{}} | {error, Reason :: term()}). +code_change(_OldVsn, State = #state{}, _Extra) -> + {ok, State}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== + +%% 查找满足条件订阅者 +-spec match_subscribers(Subscribers :: [#subscriber{}], Topic :: binary()) -> [#subscriber{}]. +match_subscribers(Subscribers, Topic) when is_list(Subscribers), is_binary(Topic) -> + Components = of_components(Topic), + lists:foldl(fun(S = #subscriber{components = Components0, subscriber_pid = Pid0}, Acc) -> + case match_components(Components0, Components) andalso not contain_channel(Pid0, Acc) of + true -> + [S|Acc]; + false -> + Acc + end + end, [], Subscribers). + +-spec contain_channel(Pid :: pid(), Subscribers :: list()) -> boolean(). +contain_channel(Pid, Subscribers) when is_pid(Pid), is_list(Subscribers) -> + lists:search(fun(#subscriber{subscriber_pid = Pid0}) -> Pid == Pid0 end, Subscribers) /= false. + +%% 开始对比订阅的topic和发布的topic的Components信息 +%% *表示单级匹配,+表示多级匹配;+只能出现一次,并且只能在末尾 +-spec match_components(list(), list()) -> boolean(). +match_components(A, B) when is_list(A), is_list(B) -> + match_components(A, B, false). +match_components([<<"+">>], [_|_], _) -> + true; +match_components([], [], _) -> + true; +match_components([<<"*">>|T0], [_|T1], _) -> + match_components(T0, T1, false); +match_components([C0|T0], [C0|T1], _) -> + match_components(T0, T1, false); +match_components(_, _, _) -> + false. + +-spec of_components(Topic :: binary()) -> [binary()]. +of_components(Topic) when is_binary(Topic) -> + binary:split(Topic, <<$/>>, [global]). + +is_valid_components([]) -> + true; +is_valid_components([<<$+>>|T]) -> + length(T) =:= 0; +is_valid_components([<<$*>>|T]) -> + is_valid_components(T); +is_valid_components([_|T]) -> + is_valid_components(T). + +-spec order_num(Components :: list()) -> integer(). +order_num([]) -> + 1; +order_num([<<$*>>|_]) -> + 2; +order_num([<<$+>>|_]) -> + 3; +order_num([_|Tail]) -> + order_num(Tail). \ No newline at end of file diff --git a/apps/iot/src/endpoint/endpoint_sup.erl b/apps/iot/src/endpoint/endpoint_sup.erl index c8bd065..ad59018 100644 --- a/apps/iot/src/endpoint/endpoint_sup.erl +++ b/apps/iot/src/endpoint/endpoint_sup.erl @@ -12,7 +12,6 @@ -export([ensured_endpoint_started/1, delete_endpoint/1]). -export([init/1]). --export([kafka_test/0]). -define(SERVER, ?MODULE). @@ -30,59 +29,22 @@ start_link() -> %% modules => modules()} % optional init([]) -> SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600}, - Endpoints = endpoint_bo:get_all_endpoints(), - ChildSpecs = lists:flatmap(fun(EndpointInfo) -> - case endpoint_bo:endpoint_record(EndpointInfo) of + Endpoints = iot_api:get_all_endpoints(), + ChildSpecs = lists:filtermap(fun(EndpointInfo) -> + case endpoint:endpoint_record(EndpointInfo) of error -> - []; + false; {ok, Endpoint} -> - [Endpoint] + case endpoint:is_support(endpoint:get_protocol(Endpoint)) of + true -> + {true, child_spec(Endpoint)}; + false -> + false + end end - end, Endpoints), + end, Endpoints), {ok, {SupFlags, ChildSpecs}}. -%% internal functions - -kafka_test() -> - Endpoint = #endpoint{ - id = 1, - %% 全局唯一,在路由规则中通过名称来指定 - name = <<"kafka_test">>, - %% 标题描述 - title = <<"kafka测试"/utf8>>, - %% 配置项, 格式: #{<<"protocol">> => <<"http|https|ws|kafka|mqtt">>, <<"args">> => #{}} - config = #kafka_endpoint{ - %sasl_config = { - % scram_sha_256, - % <<"admin">>, - % <<"lz4rP5UavRTiGZEZK8G51mxHcM5iPC">> - %}, - - sasl_config = undefined, - - bootstrap_servers = [ - {"127.0.0.1", 19092} - ], - topic = <<"metric">> - }, - status = 0, - updated_at = 0, - created_at = 0 - }, - {ok, Pid} = ensured_endpoint_started(Endpoint), - ServiceId = <<"service_id_123">>, - Metric = <<"this is a test">>, - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric), - endpoint:forward(Pid, ServiceId, Metric). - -spec ensured_endpoint_started(Endpoint :: #endpoint{}) -> {ok, Pid :: pid()} | {error, Reason :: any()}. ensured_endpoint_started(Endpoint = #endpoint{}) -> case supervisor:start_child(?MODULE, child_spec(Endpoint)) of diff --git a/apps/iot/src/endpoint/endpoint_sup_sup.erl b/apps/iot/src/endpoint/endpoint_sup_sup.erl new file mode 100644 index 0000000..8ff2b9b --- /dev/null +++ b/apps/iot/src/endpoint/endpoint_sup_sup.erl @@ -0,0 +1,49 @@ +%%%------------------------------------------------------------------- +%% @doc endpoint top level supervisor. +%% @end +%%%------------------------------------------------------------------- + +-module(endpoint_sup_sup). + +-behaviour(supervisor). +-include("endpoint.hrl"). + +-export([start_link/0]). +-export([init/1]). + +-define(SERVER, ?MODULE). + +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +%% sup_flags() = #{strategy => strategy(), % optional +%% intensity => non_neg_integer(), % optional +%% period => pos_integer()} % optional +%% child_spec() = #{id => child_id(), % mandatory +%% start => mfargs(), % mandatory +%% restart => restart(), % optional +%% shutdown => shutdown(), % optional +%% type => worker(), % optional +%% modules => modules()} % optional +init([]) -> + SupFlags = #{strategy => one_for_all, intensity => 1000, period => 3600}, + ChildSpecs = [ + #{ + id => endpoint_subscription, + start => {'endpoint_subscription', start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => ['endpoint_subscription'] + }, + + #{ + id => 'endpoint_sup', + start => {'endpoint_sup', start_link, []}, + restart => permanent, + shutdown => 2000, + type => supervisor, + modules => ['endpoint_sup'] + } + ], + {ok, {SupFlags, ChildSpecs}}. \ No newline at end of file diff --git a/apps/iot/src/http_handlers/container_handler.erl b/apps/iot/src/http_handlers/container_handler.erl new file mode 100644 index 0000000..13e3e79 --- /dev/null +++ b/apps/iot/src/http_handlers/container_handler.erl @@ -0,0 +1,309 @@ +%%%------------------------------------------------------------------- +%%% @author licheng5 +%%% @copyright (C) 2020, +%%% @doc +%%% +%%% @end +%%% Created : 26. 4月 2020 3:36 下午 +%%%------------------------------------------------------------------- +-module(container_handler). +-author("licheng5"). +-include("iot.hrl"). + +-define(REQ_TIMEOUT, 10000). + +%% API +-export([handle_request/4]). + +handle_request("GET", "/container/get_all", #{<<"uuid">> := UUID}, _) when is_binary(UUID) -> + %% 检查ConfigJson是否是合法的json字符串 + case iot_host:get_pid(UUID) of + undefined -> + {ok, 200, iot_util:json_error(-1, <<"host not found">>)}; + Pid when is_pid(Pid) -> + case iot_host:get_containers(Pid) of + {ok, Ref} -> + case iot_host:await_reply(Ref, ?REQ_TIMEOUT) of + {ok, Result} -> + {ok, 200, iot_util:json_data(Result)}; + {error, Reason} -> + {ok, 200, iot_util:json_error(-1, Reason)} + end; + {error, Reason} when is_binary(Reason) -> + {ok, 200, iot_util:json_error(-1, Reason)} + end + end; + +%% 下发config.json, 微服务接受后,保存服务配置 +handle_request("POST", "/container/push_config", _, + #{<<"uuid">> := UUID, <<"container_name">> := ContainerName, <<"config">> := Config, <<"timeout">> := Timeout0}) + when is_binary(UUID), is_binary(ContainerName), is_binary(Config), is_integer(Timeout0) -> + + %% 检查ConfigJson是否是合法的json字符串 + true = iot_util:is_json(Config), + case iot_host:get_pid(UUID) of + undefined -> + {ok, 200, iot_util:json_error(-1, <<"host not found">>)}; + Pid when is_pid(Pid) -> + Timeout = Timeout0 * 1000, + case iot_host:config_container(Pid, ContainerName, Config) of + {ok, Ref} -> + case iot_host:await_reply(Ref, Timeout) of + {ok, Result} -> + {ok, 200, iot_util:json_data(Result)}; + {error, Reason} -> + {ok, 200, iot_util:json_error(-1, Reason)} + end; + {error, Reason} when is_binary(Reason) -> + {ok, 200, iot_util:json_error(-1, Reason)} + end + end; + +%% 部署微服务 +handle_request("POST", "/container/deploy", _, #{<<"uuid">> := UUID, <<"task_id">> := TaskId, <<"config">> := Config}) + when is_binary(UUID), is_integer(TaskId), is_map(Config) -> + + case validate_config(Config) of + ok -> + case iot_host:get_pid(UUID) of + undefined -> + {ok, 200, iot_util:json_error(404, <<"host not found">>)}; + Pid when is_pid(Pid) -> + case iot_host:deploy_container(Pid, TaskId, Config) of + {ok, Ref} -> + case iot_host:await_reply(Ref, ?REQ_TIMEOUT) of + {ok, Result} -> + {ok, 200, iot_util:json_data(Result)}; + {error, Reason} -> + {ok, 200, iot_util:json_error(400, Reason)} + end; + {error, Reason} when is_binary(Reason) -> + {ok, 200, iot_util:json_error(400, Reason)} + end + end; + {error, Errors} -> + Reason = iolist_to_binary(lists:join(<<"|||">>, Errors)), + {ok, 200, iot_util:json_error(400, Reason)} + end; + +%% 启动服务 +handle_request("POST", "/container/start", _, #{<<"uuid">> := UUID, <<"container_name">> := ContainerName}) when is_binary(UUID), is_binary(ContainerName) -> + case iot_host:get_pid(UUID) of + undefined -> + {ok, 200, iot_util:json_error(404, <<"host not found">>)}; + Pid when is_pid(Pid) -> + case iot_host:start_container(Pid, ContainerName) of + {ok, Ref} -> + case iot_host:await_reply(Ref, ?REQ_TIMEOUT) of + {ok, Result} -> + {ok, 200, iot_util:json_data(Result)}; + {error, Reason} -> + {ok, 200, iot_util:json_error(400, Reason)} + end; + {error, Reason} when is_binary(Reason) -> + {ok, 200, iot_util:json_error(400, Reason)} + end + end; + +%% 停止服务 +handle_request("POST", "/container/stop", _, #{<<"uuid">> := UUID, <<"container_name">> := ContainerName}) when is_binary(UUID), is_binary(ContainerName) -> + case iot_host:get_pid(UUID) of + undefined -> + {ok, 200, iot_util:json_error(404, <<"host not found">>)}; + Pid when is_pid(Pid) -> + case iot_host:stop_container(Pid, ContainerName) of + {ok, Ref} -> + case iot_host:await_reply(Ref, ?REQ_TIMEOUT) of + {ok, Result} -> + {ok, 200, iot_util:json_data(Result)}; + {error, Reason} -> + {ok, 200, iot_util:json_error(400, Reason)} + end; + {error, Reason} when is_binary(Reason) -> + {ok, 200, iot_util:json_error(400, Reason)} + end + end; + +handle_request("POST", "/container/kill", _, #{<<"uuid">> := UUID, <<"container_name">> := ContainerName}) when is_binary(UUID), is_binary(ContainerName) -> + case iot_host:get_pid(UUID) of + undefined -> + {ok, 200, iot_util:json_error(404, <<"host not found">>)}; + Pid when is_pid(Pid) -> + case iot_host:kill_container(Pid, ContainerName) of + {ok, Ref} -> + case iot_host:await_reply(Ref, ?REQ_TIMEOUT) of + {ok, Result} -> + {ok, 200, iot_util:json_data(Result)}; + {error, Reason} -> + {ok, 200, iot_util:json_error(400, Reason)} + end; + {error, Reason} when is_binary(Reason) -> + {ok, 200, iot_util:json_error(400, Reason)} + end + end; + +%% 删除容器 +handle_request("POST", "/container/remove", _, #{<<"uuid">> := UUID, <<"container_name">> := ContainerName}) when is_binary(UUID), is_binary(ContainerName) -> + case iot_host:get_pid(UUID) of + undefined -> + {ok, 200, iot_util:json_error(404, <<"host not found">>)}; + Pid when is_pid(Pid) -> + case iot_host:remove_container(Pid, ContainerName) of + {ok, Ref} -> + case iot_host:await_reply(Ref, ?REQ_TIMEOUT) of + {ok, Result} -> + {ok, 200, iot_util:json_data(Result)}; + {error, Reason} -> + {ok, 200, iot_util:json_error(400, Reason)} + end; + {error, Reason} when is_binary(Reason) -> + {ok, 200, iot_util:json_error(400, Reason)} + end + end; + +handle_request(_, Path, _, _) -> + Path1 = list_to_binary(Path), + {ok, 200, iot_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% helper methods +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +validate_config(Config) when is_map(Config) -> + %% 必选参数 + Required = [ + {<<"image">>, binary}, + {<<"container_name">>, binary}, + {<<"command">>, {list, binary}}, + {<<"restart">>, binary} + ], + + %% 可选参数(附带默认值) + Optional = [ + {<<"privileged">>, boolean}, + {<<"envs">>, {list, binary}}, + {<<"ports">>, {list, binary}}, + {<<"expose">>, {list, binary}}, + {<<"volumes">>, {list, binary}}, + {<<"networks">>, {list, binary}}, + {<<"labels">>, {map, {binary, binary}}}, + {<<"user">>, binary}, + {<<"working_dir">>, binary}, + {<<"hostname">>, binary}, + {<<"cap_add">>, {list, binary}}, + {<<"cap_drop">>, {list, binary}}, + {<<"devices">>, {list, binary}}, + {<<"mem_limit">>, binary}, + {<<"mem_reservation">>, binary}, + {<<"cpu_shares">>, integer}, + {<<"cpus">>, number}, + {<<"ulimits">>, {map, {binary, binary}}}, + {<<"sysctls">>, {map, {binary, binary}}}, + {<<"tmpfs">>, {list, binary}}, + {<<"extra_hosts">>, {list, binary}}, + {<<"healthcheck">>, {map, {binary, any}}} + ], + + Errors1 = check_required(Config, Required), + Errors2 = check_optional(Config, Optional), + + Errors = Errors1 ++ Errors2, + case Errors of + [] -> + ok; + _ -> + {error, lists:map(fun erlang:iolist_to_binary/1, Errors)} + end. + +%%------------------------------------------------------------------------------ +%% 校验必选项 +%%------------------------------------------------------------------------------ +check_required(Config, Fields) -> + lists:foldl( + fun({Key, Type}, ErrAcc) -> + case maps:get(Key, Config, undefined) of + undefined -> + [io_lib:format("miss requied parameter: ~p", [Key]) | ErrAcc]; + Value -> + case check_type(Value, Type) of + true -> + ErrAcc; + false -> + [io_lib:format("required parameter: ~p, type must be: ~p", [Key, type_name(Type)]) | ErrAcc] + end + end + end, + [], Fields). + +%%------------------------------------------------------------------------------ +%% 校验可选项(支持默认值填充) +%%------------------------------------------------------------------------------ +check_optional(Config, Fields) -> + lists:foldl( + fun({Key, Type}, ErrAcc) -> + case maps:get(Key, Config, undefined) of + undefined -> + ErrAcc; + Value -> + case check_type(Value, Type) of + true -> + ErrAcc; + false -> + [io_lib:format("optional parameter: ~p, type must be: ~p", [Key, type_name(Type)]) | ErrAcc] + end + end + end, + [], Fields). + +%%------------------------------------------------------------------------------ +%% 类型检查辅助函数(binary版) +%%------------------------------------------------------------------------------ +-spec type_name(tuple() | atom()) -> binary(). +type_name(binary) -> + <<"string">>; +type_name(integer) -> + <<"integer">>; +type_name(number) -> + <<"number">>; +type_name(list) -> + <<"list">>; +type_name({list, binary}) -> + <<"list of string">>; +type_name({list, number}) -> + <<"list of number">>; +type_name({list, integer}) -> + <<"list of integer">>; +type_name(map) -> + <<"map">>; +type_name({map, {binary, binary}}) -> + <<"map of string:string">>; +type_name({map, {binary, any}}) -> + <<"map of string:any">>; +type_name(boolean) -> + <<"boolean">>. + +-spec check_type(Value :: any(), any()) -> boolean(). +check_type(Value, binary) -> + is_binary(Value); +check_type(Value, integer) -> + is_integer(Value); +check_type(Value, number) -> + is_number(Value); +check_type(Value, list) when is_list(Value) -> + true; +check_type(Value, {list, binary}) when is_list(Value) -> + lists:all(fun(E) -> is_binary(E) end, Value); +check_type(Value, {list, number}) when is_list(Value) -> + lists:all(fun(E) -> is_number(E) end, Value); +check_type(Value, {list, integer}) when is_list(Value) -> + lists:all(fun(E) -> is_integer(E) end, Value); +check_type(Value, map) when is_map(Value) -> + true; +check_type(Value, {map, {binary, binary}}) when is_map(Value) -> + lists:all(fun({K, V}) -> is_binary(K) andalso is_binary(V) end, maps:to_list(Value)); +check_type(Value, {map, {binary, any}}) when is_map(Value) -> + lists:all(fun({K, _}) -> is_binary(K) end, maps:to_list(Value)); +check_type(Value, boolean) -> + is_boolean(Value); +check_type(_, _) -> + false. \ No newline at end of file diff --git a/apps/iot/src/http_handlers/device_handler.erl b/apps/iot/src/http_handlers/device_handler.erl index 3c4308c..1707e23 100644 --- a/apps/iot/src/http_handlers/device_handler.erl +++ b/apps/iot/src/http_handlers/device_handler.erl @@ -45,24 +45,6 @@ handle_request("POST", "/device/delete", _, #{<<"host_id">> := HostId, <<"device {ok, 200, iot_util:json_data(<<"success">>)} end; -%% 处理主机的授权的激活 -handle_request("POST", "/device/activate", _, #{<<"host_id">> := HostId, <<"device_uuid">> := DeviceUUID, <<"auth">> := Auth}) - when is_integer(HostId), is_binary(DeviceUUID), is_boolean(Auth) -> - - AliasName = iot_host:get_alias_name(HostId), - case global:whereis_name(AliasName) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"activate device failed">>)}; - HostPid when is_pid(HostPid) -> - case iot_host:activate_device(HostPid, DeviceUUID, Auth) of - ok -> - {ok, 200, iot_util:json_data(<<"success">>)}; - {error, Reason} -> - lager:debug("[device_handler] activate device: ~p, get error: ~p", [DeviceUUID, Reason]), - {ok, 200, iot_util:json_error(404, <<"activate device failed">>)} - end - end; - handle_request(_, Path, _, _) -> Path1 = list_to_binary(Path), {ok, 200, iot_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}. \ No newline at end of file diff --git a/apps/iot/src/http_handlers/endpoint_handler.erl b/apps/iot/src/http_handlers/endpoint_handler.erl index 0e14e16..cee9c93 100644 --- a/apps/iot/src/http_handlers/endpoint_handler.erl +++ b/apps/iot/src/http_handlers/endpoint_handler.erl @@ -30,17 +30,17 @@ handle_request("POST", "/endpoint/run_statuses", _, Ids) when is_list(Ids) -> {ok, 200, iot_util:json_data(Statuses)}; handle_request("POST", "/endpoint/start", _, #{<<"id">> := Id}) when is_integer(Id) -> - case endpoint_bo:get_endpoint(Id) of + case iot_api:get_endpoint(Id) of undefined -> {ok, 200, iot_util:json_error(404, <<"endpoint not found">>)}; {ok, EndpointInfo} -> - case endpoint_bo:endpoint_record(EndpointInfo) of - {ok, Endpoint = #endpoint{name = Name}} -> + case endpoint:endpoint_record(EndpointInfo) of + {ok, Endpoint = #endpoint{title = Title}} -> case endpoint_sup:ensured_endpoint_started(Endpoint) of {ok, Pid} when is_pid(Pid) -> {ok, 200, iot_util:json_data(<<"success">>)}; {error, Reason} -> - lager:warning("[endpoint_handler] start endpoint: ~p, get error: ~p", [Name, Reason]), + lager:warning("[endpoint_handler] start endpoint: ~p, get error: ~p", [Title, Reason]), {ok, 200, iot_util:json_error(404, <<"start endpoint error">>)} end; error -> @@ -49,7 +49,7 @@ handle_request("POST", "/endpoint/start", _, #{<<"id">> := Id}) when is_integer( end; handle_request("POST", "/endpoint/stop", _, #{<<"id">> := Id}) when is_integer(Id) -> - case endpoint_bo:get_endpoint(Id) of + case iot_api:get_endpoint(Id) of undefined -> {ok, 200, iot_util:json_error(404, <<"endpoint not found">>)}; {ok, _} -> @@ -63,19 +63,19 @@ handle_request("POST", "/endpoint/stop", _, #{<<"id">> := Id}) when is_integer(I end; handle_request("POST", "/endpoint/restart", _, #{<<"id">> := Id}) when is_integer(Id) -> - case endpoint_bo:get_endpoint(Id) of + case iot_api:get_endpoint(Id) of undefined -> {ok, 200, iot_util:json_error(404, <<"endpoint not found">>)}; {ok, EndpointInfo} -> - case endpoint_bo:endpoint_record(EndpointInfo) of - {ok, Endpoint = #endpoint{name = Name}} -> + case endpoint:endpoint_record(EndpointInfo) of + {ok, Endpoint = #endpoint{title = Title}} -> case endpoint:get_pid(Id) of undefined -> case endpoint_sup:ensured_endpoint_started(Endpoint) of {ok, Pid} when is_pid(Pid) -> {ok, 200, iot_util:json_data(<<"success">>)}; {error, Reason} -> - lager:warning("[endpoint_handler] start endpoint: ~p, get error: ~p", [Name, Reason]), + lager:warning("[endpoint_handler] start endpoint: ~p, get error: ~p", [Title, Reason]), {ok, 200, iot_util:json_error(404, <<"restart endpoint error">>)} end; Pid -> @@ -85,11 +85,11 @@ handle_request("POST", "/endpoint/restart", _, #{<<"id">> := Id}) when is_intege {ok, Pid} when is_pid(Pid) -> {ok, 200, iot_util:json_data(<<"success">>)}; {error, Reason} -> - lager:warning("[endpoint_handler] start endpoint: ~p, get error: ~p", [Name, Reason]), + lager:warning("[endpoint_handler] start endpoint: ~p, get error: ~p", [Title, Reason]), {ok, 200, iot_util:json_error(404, <<"restart endpoint error">>)} end; {error, Reason} -> - lager:warning("[endpoint_handler] start endpoint: ~p, get error: ~p", [Name, Reason]), + lager:warning("[endpoint_handler] start endpoint: ~p, get error: ~p", [Title, Reason]), {ok, 200, iot_util:json_error(404, <<"stop endpoint error">>)} end end; diff --git a/apps/iot/src/http_handlers/event_stream_handler.erl b/apps/iot/src/http_handlers/event_stream_handler.erl new file mode 100644 index 0000000..048d3ad --- /dev/null +++ b/apps/iot/src/http_handlers/event_stream_handler.erl @@ -0,0 +1,47 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 08. 5月 2025 13:00 +%%%------------------------------------------------------------------- +-module(event_stream_handler). +-author("anlicheng"). + +%% API +-export([init/2]). + +init(Req0, Opts) -> + Method = binary_to_list(cowboy_req:method(Req0)), + Path = binary_to_list(cowboy_req:path(Req0)), + GetParams0 = cowboy_req:parse_qs(Req0), + GetParams = maps:from_list(GetParams0), + + #{<<"task_id">> := TaskId0} = GetParams, + TaskId = binary_to_integer(TaskId0), + + lager:debug("method: ~p, path: ~p, get: ~p", [Method, Path, GetParams]), + Req1 = cowboy_req:stream_reply(200, #{ + <<"Content-Type">> => <<"text/event-stream">>, + <<"Cache-Control">> => <<"no-cache">>, + <<"Connection">> => <<"keep-alive">> + }, Req0), + + ok = iot_event_stream_observer:add_listener(self(), TaskId), + receiver_events(TaskId, Req1), + + {ok, Req1, Opts}. + +receiver_events(TaskId, Req) -> + receive + {stream_data, TaskId, Type, Stream} -> + Data = jiffy:encode(#{<<"type">> => Type, <<"stream">> => Stream}, [force_utf8]), + Body = iolist_to_binary([<<"event: message\n">>, <<"data: ", Data/binary, "\n">>, <<"\n">>]), + ok = cowboy_req:stream_body(Body, nofin, Req), + + receiver_events(TaskId, Req); + {stream_close, TaskId, Reason} -> + CloseFrame = iolist_to_binary([<<"event: close\n">>, <<"data: ", Reason/binary, "\n">>, <<"\n">>]), + ok = cowboy_req:stream_body(CloseFrame, fin, Req) + end. \ No newline at end of file diff --git a/apps/iot/src/http_handlers/host_handler.erl b/apps/iot/src/http_handlers/host_handler.erl index 2701736..3dde9c6 100644 --- a/apps/iot/src/http_handlers/host_handler.erl +++ b/apps/iot/src/http_handlers/host_handler.erl @@ -42,20 +42,6 @@ handle_request("GET", "/host/status", #{<<"uuid">> := UUID}, _) when is_binary(U {ok, 200, iot_util:json_data(StatusInfo)} end; -%% 重新加载对应的主机信息 -handle_request("POST", "/host/reload", _, #{<<"uuid">> := UUID}) when is_binary(UUID) -> - lager:debug("[host_handler] will reload host uuid: ~p", [UUID]), - case iot_host_sup:ensured_host_started(UUID) of - {ok, Pid} when is_pid(Pid) -> - {ok, #{<<"authorize_status">> := AuthorizeStatus}} = host_bo:get_host_by_uuid(UUID), - ok = iot_host:activate(Pid, AuthorizeStatus =:= 1), - lager:debug("[host_handler] already_started reload host uuid: ~p, success", [UUID]), - {ok, 200, iot_util:json_data(<<"success">>)}; - Error -> - lager:debug("[host_handler] reload host uuid: ~p, error: ~p", [UUID, Error]), - {ok, 200, iot_util:json_error(404, <<"reload error">>)} - end; - %% 删除对应的主机信息 handle_request("POST", "/host/delete", _, #{<<"uuid">> := UUID}) when is_binary(UUID) -> case iot_host_sup:delete_host(UUID) of diff --git a/apps/iot/src/http_handlers/http_server.erl b/apps/iot/src/http_handlers/http_protocol.erl similarity index 77% rename from apps/iot/src/http_handlers/http_server.erl rename to apps/iot/src/http_handlers/http_protocol.erl index ea4debe..f8cb7b9 100644 --- a/apps/iot/src/http_handlers/http_server.erl +++ b/apps/iot/src/http_handlers/http_protocol.erl @@ -6,39 +6,12 @@ %%% @end %%% Created : 08. 5月 2025 13:00 %%%------------------------------------------------------------------- --module(http_server). +-module(http_protocol). -author("anlicheng"). %% API --export([start/0]). -export([init/2]). -%% 启动http服务 -start() -> - {ok, Props} = application:get_env(iot, http_server), - Acceptors = proplists:get_value(acceptors, Props, 50), - MaxConnections = proplists:get_value(max_connections, Props, 10240), - Backlog = proplists:get_value(backlog, Props, 1024), - Port = proplists:get_value(port, Props), - - Dispatcher = cowboy_router:compile([ - {'_', [ - {"/host/[...]", ?MODULE, [host_handler]}, - {"/service/[...]", ?MODULE, [service_handler]}, - {"/device/[...]", ?MODULE, [device_handler]} - ]} - ]), - - TransOpts = [ - {port, Port}, - {num_acceptors, Acceptors}, - {backlog, Backlog}, - {max_connections, MaxConnections} - ], - {ok, Pid} = cowboy:start_clear(http_listener, TransOpts, #{env => #{dispatch => Dispatcher}}), - - lager:debug("[http_server] the http server start at: ~p, pid is: ~p", [Port, Pid]). - init(Req0, Opts = [Mod|_]) -> Method = binary_to_list(cowboy_req:method(Req0)), Path = binary_to_list(cowboy_req:path(Req0)), diff --git a/apps/iot/src/http_handlers/service_handler.erl b/apps/iot/src/http_handlers/service_handler.erl deleted file mode 100644 index 9e511f4..0000000 --- a/apps/iot/src/http_handlers/service_handler.erl +++ /dev/null @@ -1,146 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author licheng5 -%%% @copyright (C) 2020, -%%% @doc -%%% -%%% @end -%%% Created : 26. 4月 2020 3:36 下午 -%%%------------------------------------------------------------------- --module(service_handler). --author("licheng5"). --include("iot.hrl"). - -%% API --export([handle_request/4]). - -%% 下发config.json, 微服务接受后,保存服务配置 -handle_request("POST", "/service/push_config", _, - #{<<"uuid">> := UUID, <<"service_id">> := ServiceId, <<"config_json">> := ConfigJson, <<"timeout">> := Timeout0}) - when is_binary(UUID), is_binary(ServiceId), is_binary(ConfigJson), is_integer(Timeout0) -> - - %% 检查ConfigJson是否是合法的json字符串 - true = iot_util:is_json(ConfigJson), - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(-1, <<"host not found">>)}; - Pid when is_pid(Pid) -> - Timeout = Timeout0 * 1000, - case iot_host:async_service_config(Pid, ServiceId, ConfigJson, Timeout) of - {ok, Ref} -> - case iot_host:await_reply(Ref, Timeout) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(-1, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(-1, Reason)} - end - end; - -%% 部署微服务 -handle_request("POST", "/service/deploy", _, #{<<"uuid">> := UUID, <<"task_id">> := TaskId, <<"service_id">> := ServiceId, <<"tar_url">> := TarUrl}) - when is_binary(UUID), is_integer(TaskId), is_binary(ServiceId), is_binary(TarUrl) -> - - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - case iot_host:deploy_service(Pid, TaskId, ServiceId, TarUrl) of - {ok, Ref} -> - case iot_host:await_reply(Ref, 5000) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -%% 启动服务 -handle_request("POST", "/service/start", _, #{<<"uuid">> := UUID, <<"service_id">> := ServiceId}) when is_binary(UUID), is_binary(ServiceId) -> - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - case iot_host:start_service(Pid, ServiceId) of - {ok, Ref} -> - case iot_host:await_reply(Ref, 5000) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -%% 停止服务 -handle_request("POST", "/service/stop", _, #{<<"uuid">> := UUID, <<"service_id">> := ServiceId}) when is_binary(UUID), is_binary(ServiceId) -> - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - case iot_host:stop_service(Pid, ServiceId) of - {ok, Ref} -> - case iot_host:await_reply(Ref, 5000) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -%% 远程调用微服务, 返回值的格式为json -handle_request("POST", "/service/invoke", _, #{<<"uuid">> := UUID, <<"service_id">> := ServiceId, <<"payload">> := Payload, <<"timeout">> := Timeout0}) - when is_binary(UUID), is_binary(ServiceId), is_binary(Payload), is_integer(Timeout0) -> - - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - Timeout = Timeout0 * 1000, - case iot_host:invoke_service(Pid, ServiceId, Payload, Timeout) of - {ok, Ref} -> - case iot_host:await_reply(Ref, Timeout) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -handle_request("POST", "/service/task_log", _, #{<<"uuid">> := UUID, <<"task_id">> := TaskId}) when is_binary(UUID), is_integer(TaskId) -> - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - case iot_host:task_log(Pid, TaskId) of - {ok, Ref} -> - case iot_host:await_reply(Ref, 5000) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -handle_request(_, Path, _, _) -> - Path1 = list_to_binary(Path), - {ok, 200, iot_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% helper methods -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ No newline at end of file diff --git a/apps/iot/src/iot.app.src b/apps/iot/src/iot.app.src index 487227f..0073eb7 100644 --- a/apps/iot/src/iot.app.src +++ b/apps/iot/src/iot.app.src @@ -19,7 +19,6 @@ mysql, gproc, % gpb, - esockd, mnesia, crypto, public_key, diff --git a/apps/iot/src/iot_api.erl b/apps/iot/src/iot_api.erl index a5fed49..20969ab 100644 --- a/apps/iot/src/iot_api.erl +++ b/apps/iot/src/iot_api.erl @@ -9,130 +9,191 @@ -module(iot_api). -author("anlicheng"). --behaviour(gen_server). - %% API --export([start_link/0]). -export([ai_event/1]). -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). - --define(SERVER, ?MODULE). -define(API_TOKEN, <<"wv6fGyBhl*7@AsD9">>). --record(state, { - -}). +-export([get_all_hosts/0, get_host_by_id/1, get_host_by_uuid/1, change_host_status/2]). +-export([get_host_devices/1, get_device_by_uuid/1, change_device_status/2]). +-export([get_all_endpoints/0, get_endpoint/1]). %%%=================================================================== %%% API %%%=================================================================== +-spec get_all_hosts() -> [HostUUID :: binary()]. +get_all_hosts() -> + case do_get("/get_all_hosts", []) of + {ok, Ids} -> + Ids; + _ -> + [] + end. + +-spec get_host_by_uuid(UUID :: binary()) -> undefined | {ok, HostInfo :: map()}. +get_host_by_uuid(UUID) when is_binary(UUID) -> + case do_get("/get_host_by_uuid", [{<<"uuid">>, UUID}]) of + {ok, HostInfo} -> + {ok, HostInfo}; + _ -> + undefined + end. + +-spec get_host_by_id(HostId :: integer()) -> undefined | {ok, HostInfo :: map()}. +get_host_by_id(HostId) when is_integer(HostId) -> + case do_get("/get_host_by_id", [{<<"host_id">>, integer_to_binary(HostId)}]) of + {ok, HostInfo} -> + {ok, HostInfo}; + _ -> + undefined + end. + +%% 修改主机的状态 +-spec change_host_status(UUID :: binary(), Status :: integer()) -> {ok, Result :: any()} | {error, Reason :: any()}. +change_host_status(UUID, NStatus) when is_binary(UUID), is_integer(NStatus) -> + do_post("/change_host_status", #{<<"uuid">> => UUID, <<"new_status">> => NStatus}). + +-spec get_host_devices(HostId :: integer()) -> {ok, Devices :: [map()]} | {error, Reason::any()}. +get_host_devices(HostId) when is_integer(HostId) -> + do_get("/get_host_devices", [{<<"host_id">>, integer_to_binary(HostId)}]). + +-spec get_device_by_uuid(DeviceUUID :: binary()) -> {ok, DeviceInfo :: map()} | undefined. +get_device_by_uuid(DeviceUUID) when is_binary(DeviceUUID) -> + case do_get("/get_device_by_uuid", [{<<"device_uuid">>, DeviceUUID}]) of + {ok, DeviceInfo} -> + {ok, DeviceInfo}; + _ -> + undefined + end. + +%% 修改主机的状态 +-spec change_device_status(DeviceUUID :: binary(), Status :: integer()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. +change_device_status(DeviceUUID, NStatus) when is_binary(DeviceUUID), is_integer(NStatus) -> + do_post("/change_device_status", #{<<"device_uuid">> => DeviceUUID, <<"new_status">> => NStatus}). + +%%%------------------------------------------------------------------- +%% endpoint相关的api +%%%------------------------------------------------------------------- +%% API + +-spec get_all_endpoints() -> [Endpoint :: map()]. +get_all_endpoints() -> + case do_get("/get_all_endpoints", []) of + {ok, Endpoints} -> + Endpoints; + _ -> + [] + end. + +-spec get_endpoint(Id :: integer()) -> undefined | {ok, EndpointInfo :: map()}. +get_endpoint(Id) when is_integer(Id) -> + case do_get("/get_endpoint", [{<<"id">>, integer_to_binary(Id)}]) of + {ok, EndpointInfo} when is_map(EndpointInfo) -> + {ok, EndpointInfo}; + _ -> + undefined + end. + ai_event(Id) when is_integer(Id) -> - gen_server:cast(?MODULE, {ai_event, Id}). + Token = iot_util:md5(<>), + {ok, Url} = application:get_env(iot, api_url), -%% @doc Spawns the server and registers the local name (unique) --spec(start_link() -> - {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). + Headers = [ + {<<"content-type">>, <<"application/json">>} + ], + ReqData = #{ + <<"token">> => Token, + <<"id">> => Id + }, + Body = iolist_to_binary(jiffy:encode(ReqData, [force_utf8])), + case hackney:request(post, Url, Headers, Body, [{pool, false}]) of + {ok, 200, _, ClientRef} -> + {ok, RespBody} = hackney:body(ClientRef), + lager:debug("[iot_api] send body: ~p, get error is: ~p", [Body, RespBody]), + hackney:close(ClientRef); + {ok, HttpCode, _, ClientRef} -> + {ok, RespBody} = hackney:body(ClientRef), + hackney:close(ClientRef), + lager:warning("[iot_api] send body: ~p, get error is: ~p", [Body, {HttpCode, RespBody}]); + {error, Reason} -> + lager:warning("[iot_api] send body: ~p, get error is: ~p", [Body, Reason]) + end. -%%%=================================================================== -%%% gen_server callbacks -%%%=================================================================== +%%%------------------------------------------------------------------- +%% helper methods +%%%------------------------------------------------------------------- -%% @private -%% @doc Initializes the server --spec(init(Args :: term()) -> - {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | - {stop, Reason :: term()} | ignore). -init([]) -> - {ok, #state{}}. +-spec do_post(Path :: string(), Params :: map()) -> {ok, Resp :: any()} | {error, Reason :: any()}. +do_post(Path, Params) when is_list(Path), is_map(Params) -> + {ok, BaseUrl} = application:get_env(iot, api_url), + Headers = [ + {<<"content-type">>, <<"application/json">>}, + {<<"Accept">>, <<"application/json">>} + ], + Url = BaseUrl ++ Path, + Body = iolist_to_binary(jiffy:encode(Params, [force_utf8])), + case hackney:request(post, Url, Headers, Body, [{pool, false}]) of + {ok, 200, _, ClientRef} -> + {ok, RespBody} = hackney:body(ClientRef), + lager:debug("[iot_api] request url: ~p, send body: ~p, get error is: ~p", [Url, Body, RespBody]), + hackney:close(ClientRef), + case catch jiffy:decode(RespBody, [return_maps]) of + #{<<"result">> := Result} -> + {ok, Result}; + #{<<"error">> := #{<<"code">> := Code, <<"message">> := Message}} -> + {error, {Code, Message}}; + {error, Reason} -> + {error, Reason}; + Other -> + {error, Other} + end; + {ok, HttpCode, _, ClientRef} -> + {ok, RespBody} = hackney:body(ClientRef), + hackney:close(ClientRef), + lager:warning("[iot_api] request url: ~p, send body: ~p, get error is: ~p", [Url, Body, {HttpCode, RespBody}]), + {error, {HttpCode, RespBody}}; + {error, Reason} -> + lager:warning("[iot_api] request url: ~p, send body: ~p, get error is: ~p", [Url, Body, Reason]), + {error, Reason} + end. -%% @private -%% @doc Handling call messages --spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()}, - State :: #state{}) -> - {reply, Reply :: term(), NewState :: #state{}} | - {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} | - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} | - {stop, Reason :: term(), NewState :: #state{}}). -handle_call(_Request, _From, State = #state{}) -> - {reply, ok, State}. +-spec do_get(Path :: string(), Params :: [{Key :: binary(), Val :: binary()}]) -> {ok, Resp :: any()} | {error, Reason :: any()}. +do_get(Path, Params) when is_list(Path), is_list(Params) -> + {ok, BaseUrl} = application:get_env(iot, api_url), + Headers = [ + {<<"Accept">>, <<"application/json">>} + ], -%% @private -%% @doc Handling cast messages --spec(handle_cast(Request :: term(), State :: #state{}) -> - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), NewState :: #state{}}). -handle_cast({ai_event, Id}, State = #state{}) -> - spawn_monitor(fun() -> - Token = iot_util:md5(<>), - {ok, Url} = application:get_env(iot, api_url), + Url = case length(Params) > 0 of + true -> + QS = binary_to_list(uri_string:compose_query(Params)), + BaseUrl ++ Path ++ "?" ++ QS; + false -> + BaseUrl ++ Path + end, - Headers = [ - {<<"content-type">>, <<"application/json">>} - ], - ReqData = #{ - <<"token">> => Token, - <<"id">> => Id - }, - Body = iolist_to_binary(jiffy:encode(ReqData, [force_utf8])), - case hackney:request(post, Url, Headers, Body, [{pool, false}]) of - {ok, 200, _, ClientRef} -> - {ok, RespBody} = hackney:body(ClientRef), - lager:debug("[iot_api] send body: ~p, get error is: ~p", [Body, RespBody]), - hackney:close(ClientRef); - {ok, HttpCode, _, ClientRef} -> - {ok, RespBody} = hackney:body(ClientRef), - hackney:close(ClientRef), - lager:warning("[iot_api] send body: ~p, get error is: ~p", [Body, {HttpCode, RespBody}]); - {error, Reason} -> - lager:warning("[iot_api] send body: ~p, get error is: ~p", [Body, Reason]) - end - end), - - {noreply, State}. - -%% @private -%% @doc Handling all non call/cast messages --spec(handle_info(Info :: timeout() | term(), State :: #state{}) -> - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), NewState :: #state{}}). -%% Task进程挂掉 -handle_info({'DOWN', _MRef, process, _Pid, normal}, State) -> - {noreply, State}; - -handle_info({'DOWN', _MRef, process, _Pid, Reason}, State) -> - lager:notice("[iot_api] task process down with reason: ~p", [Reason]), - {noreply, State}; - -handle_info(_Info, State = #state{}) -> - {noreply, State}. - -%% @private -%% @doc This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any -%% necessary cleaning up. When it returns, the gen_server terminates -%% with Reason. The return value is ignored. --spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), - State :: #state{}) -> term()). -terminate(_Reason, _State = #state{}) -> - ok. - -%% @private -%% @doc Convert process state when code is changed --spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{}, - Extra :: term()) -> - {ok, NewState :: #state{}} | {error, Reason :: term()}). -code_change(_OldVsn, State = #state{}, _Extra) -> - {ok, State}. - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== + case hackney:request(get, Url, Headers, <<>>, [{pool, false}]) of + {ok, 200, _, ClientRef} -> + {ok, RespBody} = hackney:body(ClientRef), + hackney:close(ClientRef), + lager:debug("[iot_api] url: ~p, get response is: ~p", [Url, RespBody]), + case catch jiffy:decode(RespBody, [return_maps]) of + #{<<"result">> := Result} -> + {ok, Result}; + #{<<"error">> := #{<<"code">> := Code, <<"message">> := Message}} -> + {error, {Code, Message}}; + {error, Reason} -> + {error, Reason}; + Other -> + {error, Other} + end; + {ok, HttpCode, _, ClientRef} -> + {ok, RespBody} = hackney:body(ClientRef), + hackney:close(ClientRef), + lager:warning("[iot_api] request url: ~p, get error is: ~p", [Url, {HttpCode, RespBody}]), + {error, {HttpCode, RespBody}}; + {error, Reason} -> + lager:warning("[iot_api] request url: ~p, get error is: ~p", [Url, Reason]), + {error, Reason} + end. \ No newline at end of file diff --git a/apps/iot/src/iot_app.erl b/apps/iot/src/iot_app.erl index 4e65d50..3534e95 100644 --- a/apps/iot/src/iot_app.erl +++ b/apps/iot/src/iot_app.erl @@ -16,10 +16,10 @@ start(_StartType, _StartArgs) -> start_mnesia(), %% 启动http服务 - http_server:start(), + start_http_server(), %% 启动tcp服务 - tcp_server:start(), + start_tcp_server(), iot_sup:start_link(). @@ -38,6 +38,56 @@ start_mnesia() -> %% 创建数据库表 ok. +start_http_server() -> + {ok, Props} = application:get_env(iot, http_server), + Acceptors = proplists:get_value(acceptors, Props, 50), + MaxConnections = proplists:get_value(max_connections, Props, 10240), + Backlog = proplists:get_value(backlog, Props, 1024), + Port = proplists:get_value(port, Props), + + Dispatcher = cowboy_router:compile([ + {'_', [ + {"/host/[...]", http_protocol, [host_handler]}, + {"/container/[...]", http_protocol, [container_handler]}, + {"/device/[...]", http_protocol, [device_handler]}, + {"/event_stream", event_stream_handler, []} + ]} + ]), + + TransOpts = #{ + max_connections => MaxConnections, + num_acceptors => Acceptors, + shutdown => brutal_kill, + socket_opts => [ + {backlog, Backlog}, + {port, Port} + ] + }, + {ok, Pid} = cowboy:start_clear(http_listener, TransOpts, #{env => #{dispatch => Dispatcher}}), + + lager:debug("[http_server] the http server start at: ~p, pid is: ~p", [Port, Pid]). + +%% 启动tcp服务 +start_tcp_server() -> + {ok, Props} = application:get_env(iot, tcp_server), + Acceptors = proplists:get_value(acceptors, Props, 50), + MaxConnections = proplists:get_value(max_connections, Props, 10240), + Backlog = proplists:get_value(backlog, Props, 1024), + Port = proplists:get_value(port, Props), + + TransOpts = #{ + max_connections => MaxConnections, + num_acceptors => Acceptors, + shutdown => brutal_kill, + socket_opts => [ + {nodelay, false}, + {backlog, Backlog}, + {port, Port} + ] + }, + {ok, _} = ranch:start_listener(tcp_server, ranch_tcp, TransOpts, tcp_channel, []), + lager:debug("[iot_app] the tcp server start at: ~p", [Port]). + -spec ensure_mnesia_schema() -> any(). ensure_mnesia_schema() -> case mnesia:system_info(use_dir) of diff --git a/apps/iot/src/iot_device.erl b/apps/iot/src/iot_device.erl index 6296372..cf7cfcb 100644 --- a/apps/iot/src/iot_device.erl +++ b/apps/iot/src/iot_device.erl @@ -10,7 +10,7 @@ -include("iot.hrl"). %% API --export([new/1, is_activated/1, change_status/2, reload/1, auth/2]). +-export([new/1, change_status/2, reload/1]). %% 终端是否授权 -define(DEVICE_AUTH_DENIED, 0). @@ -22,7 +22,6 @@ -record(device, { device_uuid :: binary(), - auth_state = ?STATE_DENIED, status = ?DEVICE_OFFLINE }). @@ -32,29 +31,24 @@ -spec new(DeviceInfo :: binary() | map()) -> error | {ok, Device :: #device{}}. new(DeviceUUID) when is_binary(DeviceUUID) -> - case device_bo:get_device_by_uuid(DeviceUUID) of - {ok, #{<<"device_uuid">> := DeviceUUID, <<"authorize_status">> := AuthorizeStatus, <<"status">> := Status}} -> - {ok, #device{device_uuid = DeviceUUID, status = Status, auth_state = auth_state(AuthorizeStatus)}}; + case iot_api:get_device_by_uuid(DeviceUUID) of + {ok, #{<<"device_uuid">> := DeviceUUID, <<"status">> := Status}} -> + {ok, #device{device_uuid = DeviceUUID, status = Status}}; undefined -> lager:warning("[iot_device] device uuid: ~p, loaded from mysql failed", [DeviceUUID]), error end; -new(#{<<"device_uuid">> := DeviceUUID, <<"authorize_status">> := AuthorizeStatus, <<"status">> := Status}) -> - {ok, #device{device_uuid = DeviceUUID, status = Status, auth_state = auth_state(AuthorizeStatus)}}. - --spec is_activated(Device :: #device{}) -> boolean(). -is_activated(#device{auth_state = AuthState}) -> - AuthState =:= ?STATE_ACTIVATED. +new(#{<<"device_uuid">> := DeviceUUID, <<"status">> := Status}) -> + {ok, #device{device_uuid = DeviceUUID, status = Status}}. -spec change_status(Device :: #device{}, NewStatus :: integer()) -> NDevice :: #device{}. change_status(Device = #device{status = Status}, NewStatus) when is_integer(NewStatus), Status =:= NewStatus -> Device; change_status(Device = #device{device_uuid = DeviceUUID}, ?DEVICE_ONLINE) -> - {ok, _} = device_bo:change_status(DeviceUUID, ?DEVICE_ONLINE), - report_event(DeviceUUID, ?DEVICE_ONLINE), + iot_api:change_device_status(DeviceUUID, ?DEVICE_ONLINE), Device#device{status = ?DEVICE_ONLINE}; change_status(Device = #device{device_uuid = DeviceUUID}, ?DEVICE_OFFLINE) -> - {ok, #{<<"status">> := Status}} = device_bo:get_device_by_uuid(DeviceUUID), + {ok, #{<<"status">> := Status}} = iot_api:get_device_by_uuid(DeviceUUID), case Status of ?DEVICE_NOT_JOINED -> lager:debug("[iot_device] device: ~p, device_maybe_offline, not joined, can not change to offline", [DeviceUUID]), @@ -63,64 +57,17 @@ change_status(Device = #device{device_uuid = DeviceUUID}, ?DEVICE_OFFLINE) -> lager:debug("[iot_device] device: ~p, device_maybe_offline, is offline, do nothing", [DeviceUUID]), Device#device{status = ?DEVICE_OFFLINE}; ?DEVICE_ONLINE -> - {ok, _} = device_bo:change_status(DeviceUUID, ?DEVICE_OFFLINE), - report_event(DeviceUUID, ?DEVICE_OFFLINE), + iot_api:change_device_status(DeviceUUID, ?DEVICE_OFFLINE), Device#device{status = ?DEVICE_OFFLINE} end. -spec reload(Device :: #device{}) -> error | {ok, NDevice :: #device{}}. reload(Device = #device{device_uuid = DeviceUUID}) -> lager:debug("[iot_device] will reload: ~p", [DeviceUUID]), - case device_bo:get_device_by_uuid(DeviceUUID) of - {ok, #{<<"authorize_status">> := AuthorizeStatus, <<"status">> := Status}} -> - {ok, Device#device{device_uuid = DeviceUUID, status = Status, auth_state = auth_state(AuthorizeStatus)}}; + case iot_api:get_device_by_uuid(DeviceUUID) of + {ok, #{<<"status">> := Status}} -> + {ok, Device#device{device_uuid = DeviceUUID, status = Status}}; undefined -> lager:warning("[iot_device] device uuid: ~p, loaded from mysql failed", [DeviceUUID]), error - end. - --spec auth(Device :: #device{}, Auth :: boolean()) -> NDevice :: #device{}. -auth(Device = #device{auth_state = StateName, device_uuid = DeviceUUID}, Auth) when is_boolean(Auth) -> - case {StateName, Auth} of - {?STATE_DENIED, false} -> - lager:debug("[iot_device] device_uuid: ~p, auth: false, will keep state_name: ~p", [DeviceUUID, ?STATE_DENIED]), - Device; - {?STATE_DENIED, true} -> - Device#device{auth_state = ?STATE_ACTIVATED}; - {?STATE_ACTIVATED, false} -> - lager:debug("[iot_device] device_uuid: ~p, auth: false, state_name from: ~p, to: ~p", [DeviceUUID, ?STATE_ACTIVATED, ?STATE_DENIED]), - Device#device{auth_state = ?STATE_DENIED}; - {?STATE_ACTIVATED, true} -> - lager:debug("[iot_device] device_uuid: ~p, auth: true, will keep state_name: ~p", [DeviceUUID, ?STATE_ACTIVATED]), - Device - end. - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== - --spec auth_state(integer()) -> atom(). -auth_state(?DEVICE_AUTH_AUTHED) -> - ?STATE_ACTIVATED; -auth_state(?DEVICE_AUTH_DENIED) -> - ?STATE_DENIED. - --spec report_event(DeviceUUID :: binary(), NewStatus :: integer()) -> no_return(). -report_event(DeviceUUID, NewStatus) when is_binary(DeviceUUID), is_integer(NewStatus) -> - TextMap = #{ - 0 => <<"离线"/utf8>>, - 1 => <<"在线"/utf8>> - }, - %% 设备的状态信息上报给中电 - Timestamp = iot_util:timestamp_of_seconds(), - FieldsList = [#{ - <<"key">> => <<"device_status">>, - <<"value">> => NewStatus, - <<"value_text">> => maps:get(NewStatus, TextMap), - <<"unit">> => 0, - <<"type">> => <<"DI">>, - <<"name">> => <<"设备状态"/utf8>>, - <<"timestamp">> => Timestamp - }], - iot_router:route_uuid(DeviceUUID, FieldsList, Timestamp), - lager:debug("[iot_device] device_uuid: ~p, route fields: ~p", [DeviceUUID, FieldsList]). \ No newline at end of file + end. \ No newline at end of file diff --git a/apps/iot/src/iot_name_server.erl b/apps/iot/src/iot_event_stream_observer.erl similarity index 62% rename from apps/iot/src/iot_name_server.erl rename to apps/iot/src/iot_event_stream_observer.erl index 92e7a33..043b90d 100644 --- a/apps/iot/src/iot_name_server.erl +++ b/apps/iot/src/iot_event_stream_observer.erl @@ -4,50 +4,41 @@ %%% @doc %%% %%% @end -%%% Created : 17. 8月 2025 00:26 +%%% Created : 26. 9月 2025 12:19 %%%------------------------------------------------------------------- --module(iot_name_server). +-module(iot_event_stream_observer). -author("anlicheng"). -behaviour(gen_server). %% API -export([start_link/0]). --export([whereis_alias/1, register/2]). +-export([add_listener/2, stream_data/3, stream_close/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(SERVER, ?MODULE). --define(TAB, iot_name_server). -record(state, { - %% #{Pid => Name} - pid_names = #{}, - refs = [] + listeners = #{} }). %%%=================================================================== %%% API %%%=================================================================== --spec register(Name :: atom(), Pid :: pid()) -> ok. -register(Name, Pid) when is_atom(Name), is_pid(Pid) -> - gen_server:call(?SERVER, {register, Name, Pid}). +-spec add_listener(ListenerPid :: pid(), TaskId :: integer()) -> ok. +add_listener(ListenerPid, TaskId) when is_pid(ListenerPid), is_integer(TaskId) -> + gen_server:call(?SERVER, {add_listener, ListenerPid, TaskId}). --spec whereis_alias(Name :: atom()) -> undefined | pid(). -whereis_alias(Name) when is_atom(Name) -> - case ets:lookup(?TAB, Name) of - [] -> - undefined; - [{Name, Pid}|_] -> - case is_process_alive(Pid) of - true -> - Pid; - false -> - undefined - end - end. +-spec stream_data(TaskId :: integer(), Type :: binary(), Stream :: binary()) -> no_return(). +stream_data(TaskId, Type, Stream) when is_integer(TaskId), is_binary(Type), is_binary(Stream) -> + gen_server:cast(?SERVER, {stream_data, TaskId, Type, Stream}). + +-spec stream_close(TaskId :: integer(), Reason :: binary()) -> no_return(). +stream_close(TaskId, Reason) when is_integer(TaskId), is_binary(Reason) -> + gen_server:cast(?SERVER, {stream_close, TaskId, Reason}). %% @doc Spawns the server and registers the local name (unique) -spec(start_link() -> @@ -65,8 +56,6 @@ start_link() -> {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {stop, Reason :: term()} | ignore). init([]) -> - %% 初始化存储 - ets:new(?TAB, [named_table, ordered_set, public, {keypos, 1}]), {ok, #state{}}. %% @private @@ -79,10 +68,9 @@ init([]) -> {noreply, NewState :: #state{}, timeout() | hibernate} | {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} | {stop, Reason :: term(), NewState :: #state{}}). -handle_call({register, Name, Pid}, _From, State = #state{refs = Refs, pid_names = PidNames}) -> - true = ets:insert(?TAB, {Name, Pid}), - MRef = erlang:monitor(process, Pid), - {reply, ok, State#state{refs = [MRef|Refs], pid_names = maps:put(Pid, Name, PidNames)}}. +handle_call({add_listener, ListenerPid, TaskId}, _From, State = #state{listeners = Listeners}) -> + erlang:monitor(process, ListenerPid), + {reply, ok, State#state{listeners = maps:put(TaskId, ListenerPid, Listeners)}}. %% @private %% @doc Handling cast messages @@ -90,7 +78,21 @@ handle_call({register, Name, Pid}, _From, State = #state{refs = Refs, pid_names {noreply, NewState :: #state{}} | {noreply, NewState :: #state{}, timeout() | hibernate} | {stop, Reason :: term(), NewState :: #state{}}). -handle_cast(_Request, State = #state{}) -> +handle_cast({stream_data, TaskId, Type, Stream}, State = #state{listeners = Listeners}) -> + case maps:find(TaskId, Listeners) of + error -> + ok; + {ok, ListenerPid} -> + is_process_alive(ListenerPid) andalso ListenerPid ! {stream_data, TaskId, Type, Stream} + end, + {noreply, State}; +handle_cast({stream_close, TaskId, Reason}, State = #state{listeners = Listeners}) -> + case maps:find(TaskId, Listeners) of + error -> + ok; + {ok, ListenerPid} -> + is_process_alive(ListenerPid) andalso ListenerPid ! {stream_close, TaskId, Reason} + end, {noreply, State}. %% @private @@ -99,20 +101,9 @@ handle_cast(_Request, State = #state{}) -> {noreply, NewState :: #state{}} | {noreply, NewState :: #state{}, timeout() | hibernate} | {stop, Reason :: term(), NewState :: #state{}}). -handle_info({'DOWN', MRef, process, Pid, Reason}, State = #state{refs = Refs, pid_names = PidNames}) -> - % lager:debug("[iot_name_server] pid: ~p, down with reason: ~p", [Reason]), - case lists:member(MRef, Refs) of - true -> - case maps:take(Pid, PidNames) of - error -> - {noreply, State#state{refs = lists:delete(MRef, Refs)}}; - {Name, NPidNames} -> - true = ets:delete(?TAB, Name), - {noreply, State#state{pid_names = NPidNames, refs = lists:delete(MRef, Refs)}} - end; - false -> - {noreply, State} - end. +handle_info({'DOWN', _Ref, process, Pid, _Reason}, State = #state{listeners = Listeners}) -> + NListeners = maps:filter(fun(_, ListenerPid) -> ListenerPid /= Pid end, Listeners), + {noreply, State#state{listeners = NListeners}}. %% @private %% @doc This function is called by a gen_server when it is about to diff --git a/apps/iot/src/iot_host.erl b/apps/iot/src/iot_host.erl index cf39329..eb42f61 100644 --- a/apps/iot/src/iot_host.erl +++ b/apps/iot/src/iot_host.erl @@ -9,7 +9,7 @@ -module(iot_host). -author("aresei"). -include("iot.hrl"). --include("message_pb.hrl"). +-include("message.hrl"). -behaviour(gen_statem). @@ -25,9 +25,9 @@ -export([get_metric/1, get_status/1]). %% 通讯相关 -export([pub/3, attach_channel/2, command/3]). --export([deploy_service/4, start_service/2, stop_service/2, invoke_service/4, async_service_config/4, task_log/2, await_reply/2]). +-export([deploy_container/3, start_container/2, stop_container/2, remove_container/2, kill_container/2, config_container/3, get_containers/1, await_reply/2]). %% 设备管理 --export([reload_device/2, delete_device/2, activate_device/3]). +-export([reload_device/2, delete_device/2]). -export([heartbeat/1]). %% gen_statem callbacks @@ -68,7 +68,7 @@ get_alias_name(HostId0) when is_integer(HostId0) -> binary_to_atom(<<"iot_host_id:", HostId/binary>>). %% 处理消息 --spec handle(Pid :: pid(), Packet :: {atom(), binary()} | {atom(), {binary(), binary()}}) -> no_return(). +-spec handle(Pid :: pid(), Packet :: {atom(), any()}) -> no_return(). handle(Pid, Packet) when is_pid(Pid) -> gen_statem:cast(Pid, {handle, Packet}). @@ -89,40 +89,54 @@ get_metric(Pid) when is_pid(Pid) -> attach_channel(Pid, ChannelPid) when is_pid(Pid), is_pid(ChannelPid) -> gen_statem:call(Pid, {attach_channel, ChannelPid}). --spec async_service_config(Pid :: pid(), ServiceId :: binary(), ConfigJson :: binary(), Timeout :: integer()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. -async_service_config(Pid, ServiceId, ConfigJson, Timeout) when is_pid(Pid), is_binary(ServiceId), is_binary(ConfigJson), is_integer(Timeout) -> - ConfigBin = message_pb:encode_msg(#push_service_config{service_id = ServiceId, config_json = ConfigJson, timeout = Timeout}), - gen_statem:call(Pid, {async_call, self(), ?PUSH_SERVICE_CONFIG, ConfigBin}). +-spec get_containers(Pid :: pid()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. +get_containers(Pid) when is_pid(Pid) -> + Request = #jsonrpc_request{method = <<"get_containers">>, params = #{}}, + EncConfigBin = message_codec:encode(?MESSAGE_JSONRPC_REQUEST, Request), + gen_statem:call(Pid, {jsonrpc_call, self(), EncConfigBin}). --spec deploy_service(Pid :: pid(), TaskId :: integer(), ServiceId :: binary(), TarUrl :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. -deploy_service(Pid, TaskId, ServiceId, TarUrl) when is_pid(Pid), is_integer(TaskId), is_binary(ServiceId), is_binary(TarUrl) -> - PushBin = message_pb:encode_msg(#deploy{task_id = TaskId, service_id = ServiceId, tar_url = TarUrl}), - gen_statem:call(Pid, {async_call, self(), ?PUSH_DEPLOY, PushBin}). +-spec config_container(Pid :: pid(), ContainerName :: binary(), ConfigJson :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. +config_container(Pid, ContainerName, ConfigJson) when is_pid(Pid), is_binary(ContainerName), is_binary(ConfigJson) -> + Request = #jsonrpc_request{method = <<"config_container">>, params = #{<<"container_name">> => ContainerName, <<"config">> => ConfigJson}}, + EncConfigBin = message_codec:encode(?MESSAGE_JSONRPC_REQUEST, Request), + gen_statem:call(Pid, {jsonrpc_call, self(), EncConfigBin}). --spec start_service(Pid :: pid(), ServiceId :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. -start_service(Pid, ServiceId) when is_pid(Pid), is_binary(ServiceId) -> - gen_statem:call(Pid, {async_call, self(), ?PUSH_START_SERVICE, ServiceId}). +-spec deploy_container(Pid :: pid(), TaskId :: integer(), Config :: map()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. +deploy_container(Pid, TaskId, Config) when is_pid(Pid), is_integer(TaskId), is_map(Config) -> + Request = #jsonrpc_request{method = <<"deploy">>, params = #{<<"task_id">> => TaskId, <<"config">> => Config}}, + EncDeployBin = message_codec:encode(?MESSAGE_JSONRPC_REQUEST, Request), + gen_statem:call(Pid, {jsonrpc_call, self(), EncDeployBin}). --spec stop_service(Pid :: pid(), ServiceId :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. -stop_service(Pid, ServiceId) when is_pid(Pid), is_binary(ServiceId) -> - gen_statem:call(Pid, {async_call, self(), ?PUSH_STOP_SERVICE, ServiceId}). +-spec start_container(Pid :: pid(), ContainerName :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. +start_container(Pid, ContainerName) when is_pid(Pid), is_binary(ContainerName) -> + Request = #jsonrpc_request{method = <<"start_container">>, params = #{<<"container_name">> => ContainerName}}, + EncCallBin = message_codec:encode(?MESSAGE_JSONRPC_REQUEST, Request), + gen_statem:call(Pid, {jsonrpc_call, self(), EncCallBin}). --spec invoke_service(Pid :: pid(), ServiceId :: binary(), Payload :: binary(), Timeout :: integer()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. -invoke_service(Pid, ServiceId, Payload, Timeout) when is_pid(Pid), is_binary(ServiceId), is_binary(Payload), is_integer(Timeout) -> - InvokeBin = message_pb:encode_msg(#invoke{service_id = ServiceId, payload = Payload, timeout = Timeout}), - gen_statem:call(Pid, {async_call, self(), ?PUSH_INVOKE, InvokeBin}). +-spec stop_container(Pid :: pid(), ContainerName :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. +stop_container(Pid, ContainerName) when is_pid(Pid), is_binary(ContainerName) -> + Request = #jsonrpc_request{method = <<"stop_container">>, params = #{<<"container_name">> => ContainerName}}, + EncCallBin = message_codec:encode(?MESSAGE_JSONRPC_REQUEST, Request), + gen_statem:call(Pid, {jsonrpc_call, self(), EncCallBin}). --spec task_log(Pid :: pid(), TaskId :: integer()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. -task_log(Pid, TaskId) when is_pid(Pid), is_integer(TaskId) -> - TaskLogBin = message_pb:encode_msg(#fetch_task_log{task_id = TaskId}), - gen_statem:call(Pid, {async_call, self(), ?PUSH_TASK_LOG, TaskLogBin}). +-spec kill_container(Pid :: pid(), ContainerName :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. +kill_container(Pid, ContainerName) when is_pid(Pid), is_binary(ContainerName) -> + Request = #jsonrpc_request{method = <<"kill_container">>, params = #{<<"container_name">> => ContainerName}}, + EncCallBin = message_codec:encode(?MESSAGE_JSONRPC_REQUEST, Request), + gen_statem:call(Pid, {jsonrpc_call, self(), EncCallBin}). + +-spec remove_container(Pid :: pid(), ContainerName :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. +remove_container(Pid, ContainerName) when is_pid(Pid), is_binary(ContainerName) -> + Request = #jsonrpc_request{method = <<"remove_container">>, params = #{<<"container_name">> => ContainerName}}, + EncCallBin = message_codec:encode(?MESSAGE_JSONRPC_REQUEST, Request), + gen_statem:call(Pid, {jsonrpc_call, self(), EncCallBin}). -spec await_reply(Ref :: reference(), Timeout :: integer()) -> {ok, Result :: binary()} | {error, Reason :: binary()}. await_reply(Ref, Timeout) when is_reference(Ref), is_integer(Timeout) -> receive - {async_call_reply, Ref, #async_call_reply{code = 1, result = Result}} -> + {jsonrpc_reply, Ref, #jsonrpc_reply{result = Result, error = undefined}} -> {ok, Result}; - {async_call_reply, Ref, #async_call_reply{code = 0, message = Message}} -> + {jsonrpc_reply, Ref, #jsonrpc_reply{result = undefined, error = #{<<"message">> := Message}}} -> {error, Message} after Timeout -> {error, <<"timeout">>} @@ -145,10 +159,6 @@ reload_device(Pid, DeviceUUID) when is_pid(Pid), is_binary(DeviceUUID) -> delete_device(Pid, DeviceUUID) when is_pid(Pid), is_binary(DeviceUUID) -> gen_statem:call(Pid, {delete_device, DeviceUUID}). --spec activate_device(Pid :: pid(), DeviceUUID :: binary(), Auth :: boolean()) -> ok | {error, Reason :: any()}. -activate_device(Pid, DeviceUUID, Auth) when is_pid(Pid), is_binary(DeviceUUID), is_boolean(Auth) -> - gen_statem:call(Pid, {activate_device, DeviceUUID, Auth}). - -spec heartbeat(Pid :: pid()) -> no_return(). heartbeat(undefined) -> ok; @@ -170,7 +180,7 @@ start_link(Name, UUID) when is_atom(Name), is_binary(UUID) -> %% gen_statem:start_link/[3,4], this function is called by the new %% process to initialize. init([UUID]) -> - case host_bo:get_host_by_uuid(UUID) of + case iot_api:get_host_by_uuid(UUID) of {ok, #{<<"id">> := HostId, <<"authorize_status">> := AuthorizeStatus}} -> %% 通过host_id注册别名, 可以避免通过查询数据库获取HostPid AliasName = get_alias_name(HostId), @@ -185,7 +195,7 @@ init([UUID]) -> end, %% 加载设备信息 - {ok, DeviceInfos} = device_bo:get_host_devices(HostId), + {ok, DeviceInfos} = iot_api:get_host_devices(HostId), Devices = lists:filtermap(fun(DeviceInfo = #{<<"device_uuid">> := DeviceUUID}) -> case iot_device:new(DeviceInfo) of error -> @@ -227,14 +237,14 @@ handle_event({call, From}, get_status, _, State = #state{channel_pid = ChannelPi {keep_state, State, [{reply, From, {ok, Reply}}]}; %% 只要channel存在,就负责将消息推送到边缘端主机 -handle_event({call, From}, {async_call, ReceiverPid, PushType, PushBin}, _, State = #state{uuid = UUID, channel_pid = ChannelPid, has_session = HasSession}) -> +handle_event({call, From}, {jsonrpc_call, ReceiverPid, RpcCall}, _, State = #state{uuid = UUID, channel_pid = ChannelPid, has_session = HasSession}) -> case HasSession andalso is_pid(ChannelPid) of true -> %% 通过websocket发送请求 - Ref = tcp_channel:async_call(ChannelPid, ReceiverPid, PushType, PushBin), + Ref = tcp_channel:jsonrpc_call(ChannelPid, ReceiverPid, RpcCall), {keep_state, State, [{reply, From, {ok, Ref}}]}; false -> - lager:debug("[iot_host] uuid: ~p, publish_type: ~p, invalid state: ~p", [UUID, PushType, state_map(State)]), + lager:debug("[iot_host] uuid: ~p, invalid state: ~p", [UUID, state_map(State)]), {keep_state, State, [{reply, From, {error, <<"主机离线,发送请求失败"/utf8>>}}]} end; @@ -294,9 +304,8 @@ handle_event({call, From}, {attach_channel, ChannelPid}, StateName, State = #sta ?STATE_ACTIVATED -> erlang:monitor(process, ChannelPid), %% 更新主机为在线状态 - {ok, AffectedRow} = host_bo:change_status(UUID, ?HOST_ONLINE), - report_event(UUID, ?HOST_ONLINE), - lager:debug("[iot_host] host_id(attach_channel) uuid: ~p, will change status, affected_row: ~p", [UUID, AffectedRow]), + ChangeResult = iot_api:change_host_status(UUID, ?HOST_ONLINE), + lager:debug("[iot_host] host_id(attach_channel) uuid: ~p, will change status, result: ~p", [UUID, ChangeResult]), {keep_state, State#state{channel_pid = ChannelPid, has_session = true}, [{reply, From, ok}]}; %% 主机未激活 ?STATE_DENIED -> @@ -327,44 +336,20 @@ handle_event({call, From}, {reload_device, DeviceUUID}, _, State = #state{device handle_event({call, From}, {delete_device, DeviceUUID}, _, State = #state{device_map = DeviceMap}) -> {keep_state, State#state{device_map = maps:remove(DeviceUUID, DeviceMap)}, [{reply, From, ok}]}; -%% 激活设备 -handle_event({call, From}, {activate_device, DeviceUUID, Auth}, _, State = #state{device_map = DeviceMap}) -> +%% todo +handle_event(cast, {handle, {data, #data{service_id = ServiceId, device_uuid = DeviceUUID, route_key = RouteKey0, metric = Metric}}}, ?STATE_ACTIVATED, + State = #state{uuid = UUID, has_session = true, device_map = DeviceMap}) -> + + lager:debug("[iot_host] metric_data host: ~p, service_id: ~p, device_uuid: ~p, route_key: ~p, metric: ~p", [UUID, ServiceId, DeviceUUID, RouteKey0, Metric]), case maps:find(DeviceUUID, DeviceMap) of error -> - {keep_state, State, [{reply, From, {error, <<"device not found">>}}]}; + lager:warning("[iot_host] host uuid: ~p, device uuid: ~p not found, metric: ~p", [UUID, DeviceUUID, Metric]), + {keep_state, State}; {ok, Device} -> - NDevice = iot_device:auth(Device, Auth), - {keep_state, State#state{device_map = maps:put(DeviceUUID, NDevice, DeviceMap)}, [{reply, From, ok}]} - end; - -%% todo -handle_event(cast, {handle, {data, #data{service_id = ServiceId, device_uuid = DeviceUUID, route_key = RouteKey0, metric = Metric}}}, ?STATE_ACTIVATED, State = #state{uuid = UUID, has_session = true, device_map = DeviceMap}) -> - lager:debug("[iot_host] metric_data host: ~p, service_id: ~p, device_uuid: ~p, route_key: ~p, metric: ~p", [UUID, ServiceId, DeviceUUID, RouteKey0, Metric]), - case DeviceUUID =/= <<"">> of - true -> - case maps:find(DeviceUUID, DeviceMap) of - error -> - lager:warning("[iot_host] host uuid: ~p, device uuid: ~p not found, metric: ~p", [UUID, DeviceUUID, Metric]), - {keep_state, State}; - {ok, Device} -> - case iot_device:is_activated(Device) of - true -> - RouteKey = get_route_key(RouteKey0), - case endpoint:get_alias_pid(RouteKey) of - undefined -> - ok; - EndpointPid -> - endpoint:forward(EndpointPid, ServiceId, Metric) - end, - NDevice = iot_device:change_status(Device, ?DEVICE_ONLINE), - {keep_state, State#state{device_map = maps:put(DeviceUUID, NDevice, DeviceMap)}}; - false -> - lager:warning("[iot_host] host uuid: ~p, device_uuid: ~p not activated, metric: ~p", [UUID, DeviceUUID, Metric]), - {keep_state, State} - end - end; - false -> - {keep_state, State} + RouteKey = get_route_key(RouteKey0), + endpoint_subscription:publish(RouteKey, ServiceId, Metric), + NDevice = iot_device:change_status(Device, ?DEVICE_ONLINE), + {keep_state, State#state{device_map = maps:put(DeviceUUID, NDevice, DeviceMap)}} end; %% ping的数据是通过aes加密后的,因此需要在有会话的情况下才行 @@ -372,10 +357,6 @@ handle_event(cast, {handle, {ping, Metrics}}, ?STATE_ACTIVATED, State = #state{u lager:debug("[iot_host] ping host_id uuid: ~p, get ping: ~p", [UUID, Metrics]), {keep_state, State#state{metrics = Metrics}}; -handle_event(cast, {handle, {inform, #service_inform{service_id = ServiceId, status = Status, timestamp = Timestamp}}}, ?STATE_ACTIVATED, State = #state{uuid = UUID, has_session = true}) -> - lager:debug("[iot_host] inform host: ~p, service_id: ~p, status: ~p, timestamp: ~p", [UUID, ServiceId, Status, Timestamp]), - {keep_state, State}; - handle_event(cast, {handle, {event, #event{service_id = ServiceId, event_type = EventType, params = Params}}}, ?STATE_ACTIVATED, State = #state{uuid = UUID, has_session = true}) -> lager:debug("[iot_host] event uuid: ~p, service_id: ~p, event_type: ~p, params: ~p", [UUID, ServiceId, EventType, Params]), %DevicePid = iot_device:get_pid(DeviceUUID), @@ -390,15 +371,14 @@ handle_event(cast, heartbeat, _, State = #state{heartbeat_counter = HeartbeatCou %% 没有收到心跳包,主机下线, 设备状态不变 handle_event(info, {timeout, _, heartbeat_ticker}, _, State = #state{uuid = UUID, heartbeat_counter = 0, channel_pid = ChannelPid}) -> lager:warning("[iot_host] uuid: ~p, heartbeat lost, devices will unknown", [UUID]), - {ok, #{<<"status">> := Status}} = host_bo:get_host_by_uuid(UUID), + {ok, #{<<"status">> := Status}} = iot_api:get_host_by_uuid(UUID), case Status of ?HOST_NOT_JOINED -> lager:debug("[iot_host] host: ~p, host_maybe_offline, host not joined, can not change to offline", [UUID]); ?HOST_OFFLINE -> lager:debug("[iot_host] host: ~p, host_maybe_offline, host now is offline, do nothing", [UUID]); ?HOST_ONLINE -> - {ok, _} = host_bo:change_status(UUID, ?HOST_OFFLINE), - report_event(UUID, ?HOST_OFFLINE) + iot_api:change_host_status(UUID, ?HOST_OFFLINE) end, %% 关闭channel,主机需要重新连接,才能保存状态的一致 @@ -443,33 +423,12 @@ code_change(_OldVsn, StateName, State = #state{}, _Extra) -> %%% Internal functions %%%=================================================================== +-spec get_route_key(binary()) -> binary(). get_route_key(<<"">>) -> - <<"default">>; + <<"/">>; get_route_key(RouteKey) when is_binary(RouteKey) -> RouteKey. --spec report_event(UUID :: binary(), NewStatus :: integer()) -> no_return(). -report_event(UUID, NewStatus) when is_binary(UUID), is_integer(NewStatus) -> - TextMap = #{ - 0 => <<"离线"/utf8>>, - 1 => <<"在线"/utf8>> - }, - - %% 设备的状态信息上报给中电 - Timestamp = iot_util:timestamp_of_seconds(), - FieldsList = [#{ - <<"key">> => <<"host_status">>, - <<"value">> => NewStatus, - <<"value_text">> => maps:get(NewStatus, TextMap), - <<"unit">> => 0, - <<"type">> => <<"DI">>, - <<"name">> => <<"主机状态"/utf8>>, - <<"timestamp">> => Timestamp - }], - %% todo 这里需要实现新的机制 - % iot_router:route_uuid(UUID, FieldsList, Timestamp), - lager:debug("[iot_host] host_uuid: ~p, route fields: ~p", [UUID, FieldsList]). - %% 将当前的state转换成map state_map(#state{host_id = HostId, uuid = UUID, has_session = HasSession, heartbeat_counter = HeartbeatCounter, channel_pid = ChannelPid, metrics = Metrics}) -> #{ diff --git a/apps/iot/src/iot_host_sup.erl b/apps/iot/src/iot_host_sup.erl index 76c28bc..26d875e 100644 --- a/apps/iot/src/iot_host_sup.erl +++ b/apps/iot/src/iot_host_sup.erl @@ -15,7 +15,7 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> - Specs = lists:map(fun child_spec/1, host_bo:get_all_hosts()), + Specs = lists:map(fun child_spec/1, iot_api:get_all_hosts()), {ok, {#{strategy => one_for_one, intensity => 1000, period => 3600}, Specs}}. diff --git a/apps/iot/src/iot_router.erl b/apps/iot/src/iot_router.erl deleted file mode 100644 index 9364ec6..0000000 --- a/apps/iot/src/iot_router.erl +++ /dev/null @@ -1,26 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 04. 7月 2023 11:30 -%%%------------------------------------------------------------------- --module(iot_router). --author("aresei"). --include("iot.hrl"). - -%% API --export([route_uuid/3]). - --spec route_uuid(RouterUUID :: binary(), Fields :: list(), Timestamp :: integer()) -> no_return(). -route_uuid(RouterUUID, Fields, Timestamp) when is_binary(RouterUUID), is_list(Fields), is_integer(Timestamp) -> - %% 查找终端设备对应的点位信息 - case redis_client:hget(RouterUUID, <<"location_code">>) of - {ok, undefined} -> - lager:warning("[iot_host] the north_data hget location_code, uuid: ~p, not found, fields: ~p", [RouterUUID, Fields]); - {ok, LocationCode} when is_binary(LocationCode) -> - iot_zd_endpoint:forward(LocationCode, Fields, Timestamp); - {error, Reason} -> - lager:warning("[iot_host] the north_data hget location_code uuid: ~p, get error: ~p, fields: ~p", [RouterUUID, Reason, Fields]) - end. \ No newline at end of file diff --git a/apps/iot/src/iot_sup.erl b/apps/iot/src/iot_sup.erl index 9c3b9ff..c84a665 100644 --- a/apps/iot/src/iot_sup.erl +++ b/apps/iot/src/iot_sup.erl @@ -29,21 +29,21 @@ init([]) -> Specs = [ #{ - id => 'iot_name_server', - start => {'iot_name_server', start_link, []}, + id => 'iot_event_stream_observer', + start => {'iot_event_stream_observer', start_link, []}, restart => permanent, shutdown => 2000, type => worker, - modules => ['iot_name_server'] + modules => ['iot_event_stream_observer'] }, #{ - id => 'endpoint_sup', - start => {'endpoint_sup', start_link, []}, + id => endpoint_sup_sup, + start => {'endpoint_sup_sup', start_link, []}, restart => permanent, shutdown => 2000, type => supervisor, - modules => ['endpoint_sup'] + modules => ['endpoint_sup_sup'] }, #{ @@ -61,7 +61,11 @@ init([]) -> %% internal functions pools() -> - {ok, Pools} = application:get_env(iot, pools), - lists:map(fun({Name, PoolArgs, WorkerArgs}) -> - poolboy:child_spec(Name, [{name, {local, Name}}|PoolArgs], WorkerArgs) - end, Pools). \ No newline at end of file + case application:get_env(iot, pools) of + undefined -> + []; + {ok, Pools} -> + lists:map(fun({Name, PoolArgs, WorkerArgs}) -> + poolboy:child_spec(Name, [{name, {local, Name}}|PoolArgs], WorkerArgs) + end, Pools) + end. diff --git a/apps/iot/src/message/message_codec.erl b/apps/iot/src/message/message_codec.erl new file mode 100644 index 0000000..085d63e --- /dev/null +++ b/apps/iot/src/message/message_codec.erl @@ -0,0 +1,134 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 17. 9月 2025 16:05 +%%%------------------------------------------------------------------- +-module(message_codec). +-author("anlicheng"). +-include("message.hrl"). + +-define(I32, 1). +-define(Bytes, 2). + +%% API +-export([encode/2, decode/1]). + +-spec encode(MessageType :: integer(), Message :: any()) -> binary(). +encode(MessageType, Message) when is_integer(MessageType) -> + Bin = encode0(Message), + <>. +encode0(#auth_request{uuid = UUID, username = Username, salt = Salt, token = Token, timestamp = Timestamp}) -> + iolist_to_binary([ + marshal(?Bytes, UUID), + marshal(?Bytes, Username), + marshal(?Bytes, Salt), + marshal(?Bytes, Token), + marshal(?I32, Timestamp) + ]); +encode0(#auth_reply{code = Code, payload = Payload}) -> + iolist_to_binary([ + marshal(?I32, Code), + marshal(?Bytes, Payload) + ]); +encode0(#jsonrpc_reply{result = Result, error = undefined}) -> + ResultBin = erlang:term_to_binary(#{<<"result">> => Result}), + iolist_to_binary([marshal(?Bytes, ResultBin)]); +encode0(#jsonrpc_reply{result = undefined, error = Error}) -> + ResultBin = erlang:term_to_binary(#{<<"error">> => Error}), + iolist_to_binary([marshal(?Bytes, ResultBin)]); +encode0(#pub{topic = Topic, content = Content}) -> + iolist_to_binary([ + marshal(?Bytes, Topic), + marshal(?Bytes, Content) + ]); +encode0(#command{command_type = CommandType, command = Command}) -> + iolist_to_binary([ + marshal(?I32, CommandType), + marshal(?Bytes, Command) + ]); + +encode0(#jsonrpc_request{method = Method, params = Params}) -> + ReqBody = erlang:term_to_binary(#{<<"method">> => Method, <<"params">> => Params}), + marshal(?Bytes, ReqBody); +encode0(#data{service_id = ServiceId, device_uuid = DeviceUUID, route_key = RouteKey, metric = Metric}) -> + iolist_to_binary([ + marshal(?Bytes, ServiceId), + marshal(?Bytes, DeviceUUID), + marshal(?Bytes, RouteKey), + marshal(?Bytes, Metric) + ]); +encode0(#event{service_id = ServiceId, event_type = EventType, params = Params}) -> + iolist_to_binary([ + marshal(?Bytes, ServiceId), + marshal(?I32, EventType), + marshal(?Bytes, Params) + ]); +encode0(#task_event_stream{task_id = TaskId, type = Type, stream = Stream}) -> + iolist_to_binary([ + marshal(?I32, TaskId), + marshal(?Bytes, Type), + marshal(?Bytes, Stream) + ]). + +-spec decode(Bin :: binary()) -> {ok, Message :: any()} | error. +decode(<>) -> + case unmarshal(Packet) of + {ok, Fields} -> + decode0(PacketType, Fields); + error -> + error + end. +decode0(?MESSAGE_AUTH_REQUEST, [UUID, Username, Salt, Token, Timestamp]) -> + {ok, #auth_request{uuid = UUID, username = Username, salt = Salt, token = Token, timestamp = Timestamp}}; +decode0(?MESSAGE_JSONRPC_REPLY, [ReplyBin]) -> + case erlang:binary_to_term(ReplyBin) of + #{<<"result">> := Result} -> + {ok, #jsonrpc_reply{result = Result}}; + #{<<"error">> := Error} -> + {ok, #jsonrpc_reply{error = Error}}; + _ -> + error + end; +decode0(?MESSAGE_PUB, [Topic, Content]) -> + {ok, #pub{topic = Topic, content = Content}}; +decode0(?MESSAGE_COMMAND, [CommandType, Command]) -> + {ok, #command{command_type = CommandType, command = Command}}; +decode0(?MESSAGE_AUTH_REPLY, [Code, Payload]) -> + {ok, #auth_reply{code = Code, payload = Payload}}; +decode0(?MESSAGE_JSONRPC_REQUEST, [ReqBody]) -> + #{<<"method">> := Method, <<"params">> := Params} = erlang:binary_to_term(ReqBody), + {ok, #jsonrpc_request{method = Method, params = Params}}; +decode0(?MESSAGE_DATA, [ServiceId, DeviceUUID, RouteKey, Metric]) -> + {ok, #data{service_id = ServiceId, device_uuid = DeviceUUID, route_key = RouteKey, metric = Metric}}; +decode0(?MESSAGE_EVENT, [ServiceId, EventType, Params]) -> + {ok, #event{service_id = ServiceId, event_type = EventType, params = Params}}; +decode0(?MESSAGE_EVENT_STREAM, [TaskId, Type, Stream]) -> + {ok, #task_event_stream{task_id = TaskId, type = Type, stream = Stream}}; +decode0(_, _) -> + error. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% helper methods +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec marshal(Type :: integer(), Field :: any()) -> binary(). +marshal(?I32, Field) when is_integer(Field) -> + <>; +marshal(?Bytes, Field) when is_binary(Field) -> + Len = byte_size(Field), + <>. + +-spec unmarshal(Bin :: binary()) -> {ok, Components :: [any()]} | error. +unmarshal(Bin) when is_binary(Bin) -> + unmarshal(Bin, []). +unmarshal(<<>>, Acc) -> + {ok, lists:reverse(Acc)}; +unmarshal(<>, Acc) -> + unmarshal(Rest, [F|Acc]); +unmarshal(<>, Acc) -> + unmarshal(Rest, [F|Acc]); +unmarshal(_, _) -> + error. diff --git a/apps/iot/src/mocker/iot_mock.erl b/apps/iot/src/mocker/iot_mock.erl index c5493c3..1968930 100644 --- a/apps/iot/src/mocker/iot_mock.erl +++ b/apps/iot/src/mocker/iot_mock.erl @@ -13,7 +13,7 @@ %% API -export([rsa_encode/1]). -export([insert_services/1]). --export([test_mqtt/0, test_influxdb/0]). +-export([test_influxdb/0]). test_influxdb() -> UUID = <<"device123123">>, @@ -29,13 +29,6 @@ test_influxdb() -> end) end, lists:seq(1, 100)). -test_mqtt() -> - iot_zd_endpoint:forward(<<"location_code_test123">>, [ - #{<<"key">> => <<"name">>, <<"value">> => <<"anlicheng">>}, - #{<<"key">> => <<"age">>, <<"value">> => 30}, - #{<<"key">> => <<"flow">>, <<"value">> => 30} - ], iot_util:timestamp_of_seconds()). - insert_services(Num) -> lists:foreach(fun(Id) -> Res = mysql_pool:insert(mysql_iot, <<"micro_service">>, diff --git a/apps/iot/src/mocker/iot_mqtt_consumer.erl b/apps/iot/src/mocker/iot_mqtt_consumer.erl deleted file mode 100644 index bef47e5..0000000 --- a/apps/iot/src/mocker/iot_mqtt_consumer.erl +++ /dev/null @@ -1,281 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% 1. 需要考虑集群部署的相关问题,上行的数据可能在集群中共享 -%%% 2. host进程不能直接去监听topic,这样涉及到新增和下线的很多问题 -%%% @end -%%% Created : 12. 3月 2023 21:27 -%%%------------------------------------------------------------------- --module(iot_mqtt_consumer). --author("aresei"). --include("iot.hrl"). - --behaviour(gen_server). - -%% API --export([start_link/0]). --export([mock/5]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). - --define(SERVER, ?MODULE). --define(RETRY_INTERVAL, 5000). - -%% 执行超时时间 --define(EXECUTE_TIMEOUT, 10 * 1000). - -%% 需要订阅的主题信息 --define(Topics,[ - {<<"CET/NX/download">>, 2} -]). - --record(state, { - conn_pid :: undefined | pid(), - logger_pid :: pid(), - mqtt_props :: list(), - %% 执行中的任务数 - flight_num = 0 -}). - -%%%=================================================================== -%%% API -%%%=================================================================== - -mock(LocationCode, Para, SType, CType, Value) when is_binary(LocationCode), is_integer(SType), is_integer(CType), is_integer(Para) -> - Req = #{ - <<"version">> => <<"1.0">>, - <<"ts">> => iot_util:current_time(), - <<"properties">> => #{ - <<"type">> => <<"ctrl">>, - <<"para">> => Para, - <<"stype">> => SType, - <<"ctype">> => CType, - <<"value">> => Value, - <<"timestamp">> => iot_util:current_time() - }, - <<"location_code">> => LocationCode - }, - gen_server:call(?MODULE, {mock, Req}). - -%% @doc Spawns the server and registers the local name (unique) --spec(start_link() -> - {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). -start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). - -%%%=================================================================== -%%% gen_server callbacks -%%%=================================================================== - -%% @private -%% @doc Initializes the server --spec(init(Args :: term()) -> - {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | - {stop, Reason :: term()} | ignore). -init([]) -> - erlang:process_flag(trap_exit, true), - - {ok, Props} = application:get_env(iot, zhongdian), - %% 创建转发器, 避免阻塞当前进程的创建,因此采用了延时初始化的机制 - erlang:start_timer(0, self(), create_consumer), - %% 启动日志记录器 - {ok, LoggerPid} = iot_logger:start_link("zd_directive_data"), - - {ok, #state{mqtt_props = Props, conn_pid = undefined, logger_pid = LoggerPid}}. - -%% @private -%% @doc Handling call messages --spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()}, - State :: #state{}) -> - {reply, Reply :: term(), NewState :: #state{}} | - {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} | - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} | - {stop, Reason :: term(), NewState :: #state{}}). -handle_call({mock, Request}, _From, State = #state{conn_pid = ConnPid, flight_num = FlightNum}) when is_pid(ConnPid) -> - publish_directive(Request, jiffy:encode(Request, [force_utf8])), - {reply, ok, State#state{flight_num = FlightNum + 1}}. - -%% @private -%% @doc Handling cast messages --spec(handle_cast(Request :: term(), State :: #state{}) -> - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), NewState :: #state{}}). -handle_cast(_Request, State = #state{}) -> - {noreply, State}. - -%% @private -%% @doc Handling all non call/cast messages --spec(handle_info(Info :: timeout() | term(), State :: #state{}) -> - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), NewState :: #state{}}). -handle_info({disconnect, ReasonCode, Properties}, State) -> - lager:debug("[iot_zd_consumer] Recv a DISONNECT packet - ReasonCode: ~p, Properties: ~p", [ReasonCode, Properties]), - {stop, disconnected, State}; -%% 必须要做到消息的快速分发,数据的json反序列需要在host进程进行 -handle_info({publish, #{packet_id := _PacketId, payload := Payload, qos := 2, topic := Topic}}, State = #state{flight_num = FlightNum}) -> - lager:debug("[iot_zd_consumer] Recv a topic: ~p, publish packet: ~ts, qos: 2", [Topic, Payload]), - - Request = catch jiffy:decode(Payload, [return_maps]), - publish_directive(Request, Payload), - - {noreply, State#state{flight_num = FlightNum + 1}}; - -handle_info({publish, #{packet_id := _PacketId, payload := Payload, qos := Qos, topic := Topic}}, State) -> - lager:notice("[iot_zd_consumer] Recv a topic: ~p, publish packet: ~ts, qos: ~p, qos is error", [Topic, Payload, Qos]), - {noreply, State}; - -handle_info({puback, Packet = #{packet_id := _PacketId}}, State = #state{}) -> - lager:debug("[iot_zd_consumer] receive puback packet: ~p", [Packet]), - {noreply, State}; - -handle_info({timeout, _, create_consumer}, State = #state{mqtt_props = Props, conn_pid = undefined}) -> - try - {ok, ConnPid} = create_consumer(Props), - {noreply, State#state{conn_pid = ConnPid}} - catch _:Error:Stack -> - lager:warning("[iot_zd_consumer] config: ~p, create consumer get error: ~p, stack: ~p", [Props, Error, Stack]), - erlang:start_timer(?RETRY_INTERVAL, self(), create_consumer), - {noreply, State#state{conn_pid = undefined}} - end; - -%% postman进程挂掉时,重新建立新的 -handle_info({'EXIT', ConnPid, Reason}, State = #state{conn_pid = ConnPid}) -> - lager:warning("[iot_zd_consumer] consumer exited with reason: ~p", [Reason]), - erlang:start_timer(?RETRY_INTERVAL, self(), create_consumer), - - {noreply, State#state{conn_pid = undefined}}; - -handle_info({'EXIT', LoggerPid, Reason}, State = #state{logger_pid = LoggerPid}) -> - lager:warning("[iot_zd_consumer] logger exited with reason: ~p", [Reason]), - {ok, LoggerPid} = iot_logger:start_link("zd_directive_data"), - - {noreply, State#state{logger_pid = LoggerPid}}; - -handle_info({directive_reply, Reply}, State = #state{logger_pid = LoggerPid, flight_num = FlightNum}) -> - FlightInfo = <<"flight_num: ", (integer_to_binary(FlightNum - 1))/binary>>, - case Reply of - {ok, RawReq, DirectiveResult} -> - case DirectiveResult of - ok -> - iot_logger:write(LoggerPid, [<<"[success]">>, RawReq, <<"OK">>, FlightInfo]); - {ok, Response} when is_binary(Response) -> - iot_logger:write(LoggerPid, [<<"[success]">>, RawReq, Response, FlightInfo]); - {error, Reason0} -> - Reason = if - is_atom(Reason0) -> atom_to_binary(Reason0); - is_binary(Reason0) -> Reason0; - true -> <<"Unknow error">> - end, - iot_logger:write(LoggerPid, [<<"[error]">>, RawReq, Reason, FlightInfo]) - end; - {error, RawReq, Error} when is_binary(Error) -> - iot_logger:write(LoggerPid, [<<"[error]">>, RawReq, Error, FlightInfo]) - end, - {noreply, State#state{flight_num = FlightNum - 1}}; - -handle_info(Info, State = #state{}) -> - lager:notice("[iot_zd_consumer] get a unknown info: ~p", [Info]), - {noreply, State}. - -%% @private -%% @doc This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any -%% necessary cleaning up. When it returns, the gen_server terminates -%% with Reason. The return value is ignored. --spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), - State :: #state{}) -> term()). -terminate(Reason, _State = #state{conn_pid = ConnPid}) when is_pid(ConnPid) -> - %% 取消topic的订阅 - TopicNames = lists:map(fun({Name, _}) -> Name end, ?Topics), - {ok, _Props, _ReasonCode} = emqtt:unsubscribe(ConnPid, #{}, TopicNames), - - ok = emqtt:disconnect(ConnPid), - lager:debug("[iot_zd_consumer] terminate with reason: ~p", [Reason]), - ok; -terminate(Reason, _State) -> - lager:debug("[iot_zd_consumer] terminate with reason: ~p", [Reason]), - ok. - -%% @private -%% @doc Convert process state when code is changed --spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{}, - Extra :: term()) -> - {ok, NewState :: #state{}} | {error, Reason :: term()}). -code_change(_OldVsn, State = #state{}, _Extra) -> - {ok, State}. - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== - -publish_directive(#{<<"version">> := Version, <<"location_code">> := LocationCode, <<"properties">> := DirectiveParams}, RawReq) -> - %% 通过LocationCode查找到主机和Device_uuid - ReceiverPid = self(), - case redis_client:hgetall(LocationCode) of - {ok, #{<<"host_uuid">> := HostUUID, <<"device_uuid">> := DeviceUUID}} -> - case iot_host:get_pid(HostUUID) of - undefined -> - ReceiverPid ! {directive_reply, {error, RawReq, <<"host uuid: ", HostUUID/binary, " not found">>}}; - Pid when is_pid(Pid) -> - ok - end; - {ok, Map} when is_map(Map) -> - RedisData = iolist_to_binary(jiffy:encode(Map, [force_utf8])), - ReceiverPid ! {directive_reply, {error, RawReq, <<"invalid redis data: ", RedisData/binary>>}}; - _ -> - ReceiverPid ! {directive_reply, {error, RawReq, <<"location_code: ", LocationCode/binary, " not found in redis">>}} - end; -publish_directive(Other, RawReq) -> - lager:warning("[iot_zd_consumer] get a error message: ~p", [Other]), - self() ! {directive_reply, {error, RawReq, <<"unknown directive">>}}. - --spec create_consumer(Props :: list()) -> {ok, ConnPid :: pid()} | {error, Reason :: any()}. -create_consumer(Props) when is_list(Props) -> - Node = atom_to_binary(node()), - ClientId = <<"mqtt-client-", Node/binary, "-zhongdian_mqtt_consumer">>, - - %% 建立到emqx服务器的连接 - Host = proplists:get_value(host, Props), - Port = proplists:get_value(port, Props, 18080), - Username = proplists:get_value(username, Props), - Password = proplists:get_value(password, Props), - Keepalive = proplists:get_value(keepalive, Props, 86400), - - Opts = [ - {clientid, ClientId}, - {host, Host}, - {port, Port}, - {owner, self()}, - {tcp_opts, []}, - {username, Username}, - {password, Password}, - {keepalive, Keepalive}, - {auto_ack, true}, - {connect_timeout, 5000}, - {proto_ver, v5}, - {retry_interval, 5000} - ], - - %% 建立到emqx服务器的连接 - lager:debug("[iot_zd_consumer] opts is: ~p", [Opts]), - case emqtt:start_link(Opts) of - {ok, ConnPid} -> - %% 监听和host相关的全部事件 - lager:debug("[iot_zd_consumer] start conntecting, pid: ~p", [ConnPid]), - {ok, _} = emqtt:connect(ConnPid), - lager:debug("[iot_zd_consumer] connect success, pid: ~p", [ConnPid]), - SubscribeResult = emqtt:subscribe(ConnPid, ?Topics), - lager:debug("[iot_zd_consumer] subscribe topics: ~p, result is: ~p", [?Topics, SubscribeResult]), - - {ok, ConnPid}; - ignore -> - {error, ignore}; - {error, Reason} -> - {error, Reason} - end. \ No newline at end of file diff --git a/apps/iot/src/protobuf/message_pb.erl b/apps/iot/src/protobuf/message_pb.erl deleted file mode 100644 index 3e6714b..0000000 --- a/apps/iot/src/protobuf/message_pb.erl +++ /dev/null @@ -1,2706 +0,0 @@ -%% -*- coding: utf-8 -*- -%% % this file is @generated -%% @private -%% Automatically generated, do not edit -%% Generated by gpb_compile version 4.21.1 -%% Version source: git --module(message_pb). - --export([encode_msg/1, encode_msg/2, encode_msg/3]). --export([decode_msg/2, decode_msg/3]). --export([merge_msgs/2, merge_msgs/3, merge_msgs/4]). --export([verify_msg/1, verify_msg/2, verify_msg/3]). --export([get_msg_defs/0]). --export([get_msg_names/0]). --export([get_group_names/0]). --export([get_msg_or_group_names/0]). --export([get_enum_names/0]). --export([find_msg_def/1, fetch_msg_def/1]). --export([find_enum_def/1, fetch_enum_def/1]). --export([enum_symbol_by_value/2, enum_value_by_symbol/2]). --export([get_service_names/0]). --export([get_service_def/1]). --export([get_rpc_names/1]). --export([find_rpc_def/2, fetch_rpc_def/2]). --export([fqbin_to_service_name/1]). --export([service_name_to_fqbin/1]). --export([fqbins_to_service_and_rpc_name/2]). --export([service_and_rpc_name_to_fqbins/2]). --export([fqbin_to_msg_name/1]). --export([msg_name_to_fqbin/1]). --export([fqbin_to_enum_name/1]). --export([enum_name_to_fqbin/1]). --export([get_package_name/0]). --export([uses_packages/0]). --export([source_basename/0]). --export([get_all_source_basenames/0]). --export([get_all_proto_names/0]). --export([get_msg_containment/1]). --export([get_pkg_containment/1]). --export([get_service_containment/1]). --export([get_rpc_containment/1]). --export([get_enum_containment/1]). --export([get_proto_by_msg_name_as_fqbin/1]). --export([get_proto_by_service_name_as_fqbin/1]). --export([get_proto_by_enum_name_as_fqbin/1]). --export([get_protos_by_pkg_name_as_fqbin/1]). --export([gpb_version_as_string/0, gpb_version_as_list/0]). --export([gpb_version_source/0]). - --include("message_pb.hrl"). --include_lib("gpb/include/gpb.hrl"). - -%% enumerated types - --export_type([]). - -%% message types --type auth_request() :: #auth_request{}. - --type auth_reply() :: #auth_reply{}. - --type pub() :: #pub{}. - --type async_call_reply() :: #async_call_reply{}. - --type deploy() :: #deploy{}. - --type fetch_task_log() :: #fetch_task_log{}. - --type invoke() :: #invoke{}. - --type push_service_config() :: #push_service_config{}. - --type data() :: #data{}. - --type ping() :: #ping{}. - --type service_inform() :: #service_inform{}. - --type event() :: #event{}. - --type alarm() :: #alarm{}. - --export_type(['auth_request'/0, 'auth_reply'/0, 'pub'/0, 'async_call_reply'/0, 'deploy'/0, 'fetch_task_log'/0, 'invoke'/0, 'push_service_config'/0, 'data'/0, 'ping'/0, 'service_inform'/0, 'event'/0, 'alarm'/0]). --type '$msg_name'() :: auth_request | auth_reply | pub | async_call_reply | deploy | fetch_task_log | invoke | push_service_config | data | ping | service_inform | event | alarm. --type '$msg'() :: auth_request() | auth_reply() | pub() | async_call_reply() | deploy() | fetch_task_log() | invoke() | push_service_config() | data() | ping() | service_inform() | event() | alarm(). --export_type(['$msg_name'/0, '$msg'/0]). - --if(?OTP_RELEASE >= 24). --dialyzer({no_underspecs, encode_msg/1}). --endif. --spec encode_msg('$msg'()) -> binary(). -encode_msg(Msg) when tuple_size(Msg) >= 1 -> encode_msg(Msg, element(1, Msg), []). - --if(?OTP_RELEASE >= 24). --dialyzer({no_underspecs, encode_msg/2}). --endif. --spec encode_msg('$msg'(), '$msg_name'() | list()) -> binary(). -encode_msg(Msg, MsgName) when is_atom(MsgName) -> encode_msg(Msg, MsgName, []); -encode_msg(Msg, Opts) when tuple_size(Msg) >= 1, is_list(Opts) -> encode_msg(Msg, element(1, Msg), Opts). - --if(?OTP_RELEASE >= 24). --dialyzer({no_underspecs, encode_msg/3}). --endif. --spec encode_msg('$msg'(), '$msg_name'(), list()) -> binary(). -encode_msg(Msg, MsgName, Opts) -> - case proplists:get_bool(verify, Opts) of - true -> verify_msg(Msg, MsgName, Opts); - false -> ok - end, - TrUserData = proplists:get_value(user_data, Opts), - case MsgName of - auth_request -> encode_msg_auth_request(id(Msg, TrUserData), TrUserData); - auth_reply -> encode_msg_auth_reply(id(Msg, TrUserData), TrUserData); - pub -> encode_msg_pub(id(Msg, TrUserData), TrUserData); - async_call_reply -> encode_msg_async_call_reply(id(Msg, TrUserData), TrUserData); - deploy -> encode_msg_deploy(id(Msg, TrUserData), TrUserData); - fetch_task_log -> encode_msg_fetch_task_log(id(Msg, TrUserData), TrUserData); - invoke -> encode_msg_invoke(id(Msg, TrUserData), TrUserData); - push_service_config -> encode_msg_push_service_config(id(Msg, TrUserData), TrUserData); - data -> encode_msg_data(id(Msg, TrUserData), TrUserData); - ping -> encode_msg_ping(id(Msg, TrUserData), TrUserData); - service_inform -> encode_msg_service_inform(id(Msg, TrUserData), TrUserData); - event -> encode_msg_event(id(Msg, TrUserData), TrUserData); - alarm -> encode_msg_alarm(id(Msg, TrUserData), TrUserData) - end. - - -encode_msg_auth_request(Msg, TrUserData) -> encode_msg_auth_request(Msg, <<>>, TrUserData). - - -encode_msg_auth_request(#auth_request{uuid = F1, username = F2, salt = F3, token = F4, timestamp = F5}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case is_empty_string(TrF2) of - true -> B1; - false -> e_type_string(TrF2, <>, TrUserData) - end - end - end, - B3 = if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - case is_empty_string(TrF3) of - true -> B2; - false -> e_type_string(TrF3, <>, TrUserData) - end - end - end, - B4 = if F4 == undefined -> B3; - true -> - begin - TrF4 = id(F4, TrUserData), - case is_empty_string(TrF4) of - true -> B3; - false -> e_type_string(TrF4, <>, TrUserData) - end - end - end, - if F5 == undefined -> B4; - true -> - begin - TrF5 = id(F5, TrUserData), - if TrF5 =:= 0 -> B4; - true -> e_varint(TrF5, <>, TrUserData) - end - end - end. - -encode_msg_auth_reply(Msg, TrUserData) -> encode_msg_auth_reply(Msg, <<>>, TrUserData). - - -encode_msg_auth_reply(#auth_reply{code = F1, message = F2}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - if TrF1 =:= 0 -> Bin; - true -> e_varint(TrF1, <>, TrUserData) - end - end - end, - if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case is_empty_string(TrF2) of - true -> B1; - false -> e_type_string(TrF2, <>, TrUserData) - end - end - end. - -encode_msg_pub(Msg, TrUserData) -> encode_msg_pub(Msg, <<>>, TrUserData). - - -encode_msg_pub(#pub{topic = F1, content = F2}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case iolist_size(TrF2) of - 0 -> B1; - _ -> e_type_bytes(TrF2, <>, TrUserData) - end - end - end. - -encode_msg_async_call_reply(Msg, TrUserData) -> encode_msg_async_call_reply(Msg, <<>>, TrUserData). - - -encode_msg_async_call_reply(#async_call_reply{code = F1, result = F2, message = F3}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - if TrF1 =:= 0 -> Bin; - true -> e_varint(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case is_empty_string(TrF2) of - true -> B1; - false -> e_type_string(TrF2, <>, TrUserData) - end - end - end, - if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - case is_empty_string(TrF3) of - true -> B2; - false -> e_type_string(TrF3, <>, TrUserData) - end - end - end. - -encode_msg_deploy(Msg, TrUserData) -> encode_msg_deploy(Msg, <<>>, TrUserData). - - -encode_msg_deploy(#deploy{task_id = F1, service_id = F2, tar_url = F3}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - if TrF1 =:= 0 -> Bin; - true -> e_varint(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case is_empty_string(TrF2) of - true -> B1; - false -> e_type_string(TrF2, <>, TrUserData) - end - end - end, - if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - case is_empty_string(TrF3) of - true -> B2; - false -> e_type_string(TrF3, <>, TrUserData) - end - end - end. - -encode_msg_fetch_task_log(Msg, TrUserData) -> encode_msg_fetch_task_log(Msg, <<>>, TrUserData). - - -encode_msg_fetch_task_log(#fetch_task_log{task_id = F1}, Bin, TrUserData) -> - if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - if TrF1 =:= 0 -> Bin; - true -> e_varint(TrF1, <>, TrUserData) - end - end - end. - -encode_msg_invoke(Msg, TrUserData) -> encode_msg_invoke(Msg, <<>>, TrUserData). - - -encode_msg_invoke(#invoke{service_id = F1, payload = F2, timeout = F3}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case iolist_size(TrF2) of - 0 -> B1; - _ -> e_type_bytes(TrF2, <>, TrUserData) - end - end - end, - if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - if TrF3 =:= 0 -> B2; - true -> e_varint(TrF3, <>, TrUserData) - end - end - end. - -encode_msg_push_service_config(Msg, TrUserData) -> encode_msg_push_service_config(Msg, <<>>, TrUserData). - - -encode_msg_push_service_config(#push_service_config{service_id = F1, config_json = F2, timeout = F3}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case is_empty_string(TrF2) of - true -> B1; - false -> e_type_string(TrF2, <>, TrUserData) - end - end - end, - if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - if TrF3 =:= 0 -> B2; - true -> e_varint(TrF3, <>, TrUserData) - end - end - end. - -encode_msg_data(Msg, TrUserData) -> encode_msg_data(Msg, <<>>, TrUserData). - - -encode_msg_data(#data{service_id = F1, device_uuid = F2, route_key = F3, metric = F4}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case is_empty_string(TrF2) of - true -> B1; - false -> e_type_string(TrF2, <>, TrUserData) - end - end - end, - B3 = if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - case is_empty_string(TrF3) of - true -> B2; - false -> e_type_string(TrF3, <>, TrUserData) - end - end - end, - if F4 == undefined -> B3; - true -> - begin - TrF4 = id(F4, TrUserData), - case iolist_size(TrF4) of - 0 -> B3; - _ -> e_type_bytes(TrF4, <>, TrUserData) - end - end - end. - -encode_msg_ping(Msg, TrUserData) -> encode_msg_ping(Msg, <<>>, TrUserData). - - -encode_msg_ping(#ping{adcode = F1, boot_time = F2, province = F3, city = F4, efka_version = F5, kernel_arch = F6, ips = F7, cpu_core = F8, cpu_load = F9, cpu_temperature = F10, disk = F11, memory = F12, interfaces = F13}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - if TrF2 =:= 0 -> B1; - true -> e_varint(TrF2, <>, TrUserData) - end - end - end, - B3 = if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - case is_empty_string(TrF3) of - true -> B2; - false -> e_type_string(TrF3, <>, TrUserData) - end - end - end, - B4 = if F4 == undefined -> B3; - true -> - begin - TrF4 = id(F4, TrUserData), - case is_empty_string(TrF4) of - true -> B3; - false -> e_type_string(TrF4, <>, TrUserData) - end - end - end, - B5 = if F5 == undefined -> B4; - true -> - begin - TrF5 = id(F5, TrUserData), - case is_empty_string(TrF5) of - true -> B4; - false -> e_type_string(TrF5, <>, TrUserData) - end - end - end, - B6 = if F6 == undefined -> B5; - true -> - begin - TrF6 = id(F6, TrUserData), - case is_empty_string(TrF6) of - true -> B5; - false -> e_type_string(TrF6, <>, TrUserData) - end - end - end, - B7 = begin - TrF7 = id(F7, TrUserData), - if TrF7 == [] -> B6; - true -> e_field_ping_ips(TrF7, B6, TrUserData) - end - end, - B8 = if F8 == undefined -> B7; - true -> - begin - TrF8 = id(F8, TrUserData), - if TrF8 =:= 0 -> B7; - true -> e_varint(TrF8, <>, TrUserData) - end - end - end, - B9 = if F9 == undefined -> B8; - true -> - begin - TrF9 = id(F9, TrUserData), - if TrF9 =:= 0 -> B8; - true -> e_varint(TrF9, <>, TrUserData) - end - end - end, - B10 = if F10 == undefined -> B9; - true -> - begin - TrF10 = id(F10, TrUserData), - if TrF10 =:= +0.0; TrF10 =:= 0 -> B9; - true -> e_type_float(TrF10, <>, TrUserData) - end - end - end, - B11 = begin - TrF11 = id(F11, TrUserData), - if TrF11 == [] -> B10; - true -> e_field_ping_disk(TrF11, B10, TrUserData) - end - end, - B12 = begin - TrF12 = id(F12, TrUserData), - if TrF12 == [] -> B11; - true -> e_field_ping_memory(TrF12, B11, TrUserData) - end - end, - if F13 == undefined -> B12; - true -> - begin - TrF13 = id(F13, TrUserData), - case is_empty_string(TrF13) of - true -> B12; - false -> e_type_string(TrF13, <>, TrUserData) - end - end - end. - -encode_msg_service_inform(Msg, TrUserData) -> encode_msg_service_inform(Msg, <<>>, TrUserData). - - -encode_msg_service_inform(#service_inform{service_id = F1, props = F2, status = F3, timestamp = F4}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case is_empty_string(TrF2) of - true -> B1; - false -> e_type_string(TrF2, <>, TrUserData) - end - end - end, - B3 = if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - if TrF3 =:= 0 -> B2; - true -> e_varint(TrF3, <>, TrUserData) - end - end - end, - if F4 == undefined -> B3; - true -> - begin - TrF4 = id(F4, TrUserData), - if TrF4 =:= 0 -> B3; - true -> e_varint(TrF4, <>, TrUserData) - end - end - end. - -encode_msg_event(Msg, TrUserData) -> encode_msg_event(Msg, <<>>, TrUserData). - - -encode_msg_event(#event{service_id = F1, event_type = F2, params = F3}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - B2 = if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - if TrF2 =:= 0 -> B1; - true -> e_varint(TrF2, <>, TrUserData) - end - end - end, - if F3 == undefined -> B2; - true -> - begin - TrF3 = id(F3, TrUserData), - case is_empty_string(TrF3) of - true -> B2; - false -> e_type_string(TrF3, <>, TrUserData) - end - end - end. - -encode_msg_alarm(Msg, TrUserData) -> encode_msg_alarm(Msg, <<>>, TrUserData). - - -encode_msg_alarm(#alarm{service_id = F1, params = F2}, Bin, TrUserData) -> - B1 = if F1 == undefined -> Bin; - true -> - begin - TrF1 = id(F1, TrUserData), - case is_empty_string(TrF1) of - true -> Bin; - false -> e_type_string(TrF1, <>, TrUserData) - end - end - end, - if F2 == undefined -> B1; - true -> - begin - TrF2 = id(F2, TrUserData), - case is_empty_string(TrF2) of - true -> B1; - false -> e_type_string(TrF2, <>, TrUserData) - end - end - end. - -e_field_ping_ips([Elem | Rest], Bin, TrUserData) -> - Bin2 = <>, - Bin3 = e_type_string(id(Elem, TrUserData), Bin2, TrUserData), - e_field_ping_ips(Rest, Bin3, TrUserData); -e_field_ping_ips([], Bin, _TrUserData) -> Bin. - -e_field_ping_disk(Elems, Bin, TrUserData) when Elems =/= [] -> - SubBin = e_pfield_ping_disk(Elems, <<>>, TrUserData), - Bin2 = <>, - Bin3 = e_varint(byte_size(SubBin), Bin2), - <>; -e_field_ping_disk([], Bin, _TrUserData) -> Bin. - -e_pfield_ping_disk([Value | Rest], Bin, TrUserData) -> - Bin2 = e_type_int32(id(Value, TrUserData), Bin, TrUserData), - e_pfield_ping_disk(Rest, Bin2, TrUserData); -e_pfield_ping_disk([], Bin, _TrUserData) -> Bin. - -e_field_ping_memory(Elems, Bin, TrUserData) when Elems =/= [] -> - SubBin = e_pfield_ping_memory(Elems, <<>>, TrUserData), - Bin2 = <>, - Bin3 = e_varint(byte_size(SubBin), Bin2), - <>; -e_field_ping_memory([], Bin, _TrUserData) -> Bin. - -e_pfield_ping_memory([Value | Rest], Bin, TrUserData) -> - Bin2 = e_type_int32(id(Value, TrUserData), Bin, TrUserData), - e_pfield_ping_memory(Rest, Bin2, TrUserData); -e_pfield_ping_memory([], Bin, _TrUserData) -> Bin. - --compile({nowarn_unused_function,e_type_sint/3}). -e_type_sint(Value, Bin, _TrUserData) when Value >= 0 -> e_varint(Value * 2, Bin); -e_type_sint(Value, Bin, _TrUserData) -> e_varint(Value * -2 - 1, Bin). - --compile({nowarn_unused_function,e_type_int32/3}). -e_type_int32(Value, Bin, _TrUserData) when 0 =< Value, Value =< 127 -> <>; -e_type_int32(Value, Bin, _TrUserData) -> - <> = <>, - e_varint(N, Bin). - --compile({nowarn_unused_function,e_type_int64/3}). -e_type_int64(Value, Bin, _TrUserData) when 0 =< Value, Value =< 127 -> <>; -e_type_int64(Value, Bin, _TrUserData) -> - <> = <>, - e_varint(N, Bin). - --compile({nowarn_unused_function,e_type_bool/3}). -e_type_bool(true, Bin, _TrUserData) -> <>; -e_type_bool(false, Bin, _TrUserData) -> <>; -e_type_bool(1, Bin, _TrUserData) -> <>; -e_type_bool(0, Bin, _TrUserData) -> <>. - --compile({nowarn_unused_function,e_type_string/3}). -e_type_string(S, Bin, _TrUserData) -> - Utf8 = unicode:characters_to_binary(S), - Bin2 = e_varint(byte_size(Utf8), Bin), - <>. - --compile({nowarn_unused_function,e_type_bytes/3}). -e_type_bytes(Bytes, Bin, _TrUserData) when is_binary(Bytes) -> - Bin2 = e_varint(byte_size(Bytes), Bin), - <>; -e_type_bytes(Bytes, Bin, _TrUserData) when is_list(Bytes) -> - BytesBin = iolist_to_binary(Bytes), - Bin2 = e_varint(byte_size(BytesBin), Bin), - <>. - --compile({nowarn_unused_function,e_type_fixed32/3}). -e_type_fixed32(Value, Bin, _TrUserData) -> <>. - --compile({nowarn_unused_function,e_type_sfixed32/3}). -e_type_sfixed32(Value, Bin, _TrUserData) -> <>. - --compile({nowarn_unused_function,e_type_fixed64/3}). -e_type_fixed64(Value, Bin, _TrUserData) -> <>. - --compile({nowarn_unused_function,e_type_sfixed64/3}). -e_type_sfixed64(Value, Bin, _TrUserData) -> <>. - --compile({nowarn_unused_function,e_type_float/3}). -e_type_float(V, Bin, _) when is_number(V) -> <>; -e_type_float(infinity, Bin, _) -> <>; -e_type_float('-infinity', Bin, _) -> <>; -e_type_float(nan, Bin, _) -> <>. - --compile({nowarn_unused_function,e_type_double/3}). -e_type_double(V, Bin, _) when is_number(V) -> <>; -e_type_double(infinity, Bin, _) -> <>; -e_type_double('-infinity', Bin, _) -> <>; -e_type_double(nan, Bin, _) -> <>. - --compile({nowarn_unused_function,e_unknown_elems/2}). -e_unknown_elems([Elem | Rest], Bin) -> - BinR = case Elem of - {varint, FNum, N} -> - BinF = e_varint(FNum bsl 3, Bin), - e_varint(N, BinF); - {length_delimited, FNum, Data} -> - BinF = e_varint(FNum bsl 3 bor 2, Bin), - BinL = e_varint(byte_size(Data), BinF), - <>; - {group, FNum, GroupFields} -> - Bin1 = e_varint(FNum bsl 3 bor 3, Bin), - Bin2 = e_unknown_elems(GroupFields, Bin1), - e_varint(FNum bsl 3 bor 4, Bin2); - {fixed32, FNum, V} -> - BinF = e_varint(FNum bsl 3 bor 5, Bin), - <>; - {fixed64, FNum, V} -> - BinF = e_varint(FNum bsl 3 bor 1, Bin), - <> - end, - e_unknown_elems(Rest, BinR); -e_unknown_elems([], Bin) -> Bin. - --compile({nowarn_unused_function,e_varint/3}). -e_varint(N, Bin, _TrUserData) -> e_varint(N, Bin). - --compile({nowarn_unused_function,e_varint/2}). -e_varint(N, Bin) when N =< 127 -> <>; -e_varint(N, Bin) -> - Bin2 = <>, - e_varint(N bsr 7, Bin2). - -is_empty_string("") -> true; -is_empty_string(<<>>) -> true; -is_empty_string(L) when is_list(L) -> not string_has_chars(L); -is_empty_string(B) when is_binary(B) -> false. - -string_has_chars([C | _]) when is_integer(C) -> true; -string_has_chars([H | T]) -> - case string_has_chars(H) of - true -> true; - false -> string_has_chars(T) - end; -string_has_chars(B) when is_binary(B), byte_size(B) =/= 0 -> true; -string_has_chars(C) when is_integer(C) -> true; -string_has_chars(<<>>) -> false; -string_has_chars([]) -> false. - - -decode_msg(Bin, MsgName) when is_binary(Bin) -> decode_msg(Bin, MsgName, []). - -decode_msg(Bin, MsgName, Opts) when is_binary(Bin) -> - TrUserData = proplists:get_value(user_data, Opts), - decode_msg_1_catch(Bin, MsgName, TrUserData). - --ifdef('OTP_RELEASE'). -decode_msg_1_catch(Bin, MsgName, TrUserData) -> - try decode_msg_2_doit(MsgName, Bin, TrUserData) - catch - error:{gpb_error,_}=Reason:StackTrace -> - erlang:raise(error, Reason, StackTrace); - Class:Reason:StackTrace -> error({gpb_error,{decoding_failure, {Bin, MsgName, {Class, Reason, StackTrace}}}}) - end. --else. -decode_msg_1_catch(Bin, MsgName, TrUserData) -> - try decode_msg_2_doit(MsgName, Bin, TrUserData) - catch - error:{gpb_error,_}=Reason -> - erlang:raise(error, Reason, - erlang:get_stacktrace()); - Class:Reason -> - StackTrace = erlang:get_stacktrace(), - error({gpb_error,{decoding_failure, {Bin, MsgName, {Class, Reason, StackTrace}}}}) - end. --endif. - -decode_msg_2_doit(auth_request, Bin, TrUserData) -> id(decode_msg_auth_request(Bin, TrUserData), TrUserData); -decode_msg_2_doit(auth_reply, Bin, TrUserData) -> id(decode_msg_auth_reply(Bin, TrUserData), TrUserData); -decode_msg_2_doit(pub, Bin, TrUserData) -> id(decode_msg_pub(Bin, TrUserData), TrUserData); -decode_msg_2_doit(async_call_reply, Bin, TrUserData) -> id(decode_msg_async_call_reply(Bin, TrUserData), TrUserData); -decode_msg_2_doit(deploy, Bin, TrUserData) -> id(decode_msg_deploy(Bin, TrUserData), TrUserData); -decode_msg_2_doit(fetch_task_log, Bin, TrUserData) -> id(decode_msg_fetch_task_log(Bin, TrUserData), TrUserData); -decode_msg_2_doit(invoke, Bin, TrUserData) -> id(decode_msg_invoke(Bin, TrUserData), TrUserData); -decode_msg_2_doit(push_service_config, Bin, TrUserData) -> id(decode_msg_push_service_config(Bin, TrUserData), TrUserData); -decode_msg_2_doit(data, Bin, TrUserData) -> id(decode_msg_data(Bin, TrUserData), TrUserData); -decode_msg_2_doit(ping, Bin, TrUserData) -> id(decode_msg_ping(Bin, TrUserData), TrUserData); -decode_msg_2_doit(service_inform, Bin, TrUserData) -> id(decode_msg_service_inform(Bin, TrUserData), TrUserData); -decode_msg_2_doit(event, Bin, TrUserData) -> id(decode_msg_event(Bin, TrUserData), TrUserData); -decode_msg_2_doit(alarm, Bin, TrUserData) -> id(decode_msg_alarm(Bin, TrUserData), TrUserData). - - - -decode_msg_auth_request(Bin, TrUserData) -> dfp_read_field_def_auth_request(Bin, 0, 0, 0, id(<<>>, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), id(0, TrUserData), TrUserData). - -dfp_read_field_def_auth_request(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_auth_request_uuid(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -dfp_read_field_def_auth_request(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_auth_request_username(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -dfp_read_field_def_auth_request(<<34, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_auth_request_salt(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -dfp_read_field_def_auth_request(<<42, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_auth_request_token(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -dfp_read_field_def_auth_request(<<48, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_auth_request_timestamp(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -dfp_read_field_def_auth_request(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, _) -> #auth_request{uuid = F@_1, username = F@_2, salt = F@_3, token = F@_4, timestamp = F@_5}; -dfp_read_field_def_auth_request(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> dg_read_field_def_auth_request(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). - -dg_read_field_def_auth_request(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 32 - 7 -> dg_read_field_def_auth_request(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -dg_read_field_def_auth_request(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_auth_request_uuid(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - 18 -> d_field_auth_request_username(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - 34 -> d_field_auth_request_salt(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - 42 -> d_field_auth_request_token(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - 48 -> d_field_auth_request_timestamp(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_auth_request(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - 1 -> skip_64_auth_request(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - 2 -> skip_length_delimited_auth_request(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - 3 -> skip_group_auth_request(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); - 5 -> skip_32_auth_request(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) - end - end; -dg_read_field_def_auth_request(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, _) -> #auth_request{uuid = F@_1, username = F@_2, salt = F@_3, token = F@_4, timestamp = F@_5}. - -d_field_auth_request_uuid(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_auth_request_uuid(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -d_field_auth_request_uuid(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, F@_4, F@_5, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_auth_request(RestF, 0, 0, F, NewFValue, F@_2, F@_3, F@_4, F@_5, TrUserData). - -d_field_auth_request_username(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_auth_request_username(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -d_field_auth_request_username(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, F@_4, F@_5, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_auth_request(RestF, 0, 0, F, F@_1, NewFValue, F@_3, F@_4, F@_5, TrUserData). - -d_field_auth_request_salt(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_auth_request_salt(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -d_field_auth_request_salt(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, F@_4, F@_5, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_auth_request(RestF, 0, 0, F, F@_1, F@_2, NewFValue, F@_4, F@_5, TrUserData). - -d_field_auth_request_token(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_auth_request_token(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -d_field_auth_request_token(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, _, F@_5, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_auth_request(RestF, 0, 0, F, F@_1, F@_2, F@_3, NewFValue, F@_5, TrUserData). - -d_field_auth_request_timestamp(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_auth_request_timestamp(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -d_field_auth_request_timestamp(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, _, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_auth_request(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, NewFValue, TrUserData). - -skip_varint_auth_request(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> skip_varint_auth_request(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -skip_varint_auth_request(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> dfp_read_field_def_auth_request(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). - -skip_length_delimited_auth_request(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> skip_length_delimited_auth_request(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); -skip_length_delimited_auth_request(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_auth_request(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). - -skip_group_auth_request(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_auth_request(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). - -skip_32_auth_request(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> dfp_read_field_def_auth_request(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). - -skip_64_auth_request(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> dfp_read_field_def_auth_request(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). - -decode_msg_auth_reply(Bin, TrUserData) -> dfp_read_field_def_auth_reply(Bin, 0, 0, 0, id(0, TrUserData), id(<<>>, TrUserData), TrUserData). - -dfp_read_field_def_auth_reply(<<8, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> d_field_auth_reply_code(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -dfp_read_field_def_auth_reply(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> d_field_auth_reply_message(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -dfp_read_field_def_auth_reply(<<>>, 0, 0, _, F@_1, F@_2, _) -> #auth_reply{code = F@_1, message = F@_2}; -dfp_read_field_def_auth_reply(Other, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dg_read_field_def_auth_reply(Other, Z1, Z2, F, F@_1, F@_2, TrUserData). - -dg_read_field_def_auth_reply(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 32 - 7 -> dg_read_field_def_auth_reply(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -dg_read_field_def_auth_reply(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 8 -> d_field_auth_reply_code(Rest, 0, 0, 0, F@_1, F@_2, TrUserData); - 18 -> d_field_auth_reply_message(Rest, 0, 0, 0, F@_1, F@_2, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_auth_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 1 -> skip_64_auth_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 2 -> skip_length_delimited_auth_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 3 -> skip_group_auth_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 5 -> skip_32_auth_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData) - end - end; -dg_read_field_def_auth_reply(<<>>, 0, 0, _, F@_1, F@_2, _) -> #auth_reply{code = F@_1, message = F@_2}. - -d_field_auth_reply_code(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> d_field_auth_reply_code(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -d_field_auth_reply_code(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_auth_reply(RestF, 0, 0, F, NewFValue, F@_2, TrUserData). - -d_field_auth_reply_message(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> d_field_auth_reply_message(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -d_field_auth_reply_message(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_auth_reply(RestF, 0, 0, F, F@_1, NewFValue, TrUserData). - -skip_varint_auth_reply(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> skip_varint_auth_reply(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -skip_varint_auth_reply(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_auth_reply(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -skip_length_delimited_auth_reply(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> skip_length_delimited_auth_reply(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -skip_length_delimited_auth_reply(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_auth_reply(Rest2, 0, 0, F, F@_1, F@_2, TrUserData). - -skip_group_auth_reply(Bin, _, Z2, FNum, F@_1, F@_2, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_auth_reply(Rest, 0, Z2, FNum, F@_1, F@_2, TrUserData). - -skip_32_auth_reply(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_auth_reply(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -skip_64_auth_reply(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_auth_reply(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -decode_msg_pub(Bin, TrUserData) -> dfp_read_field_def_pub(Bin, 0, 0, 0, id(<<>>, TrUserData), id(<<>>, TrUserData), TrUserData). - -dfp_read_field_def_pub(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> d_field_pub_topic(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -dfp_read_field_def_pub(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> d_field_pub_content(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -dfp_read_field_def_pub(<<>>, 0, 0, _, F@_1, F@_2, _) -> #pub{topic = F@_1, content = F@_2}; -dfp_read_field_def_pub(Other, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dg_read_field_def_pub(Other, Z1, Z2, F, F@_1, F@_2, TrUserData). - -dg_read_field_def_pub(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 32 - 7 -> dg_read_field_def_pub(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -dg_read_field_def_pub(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_pub_topic(Rest, 0, 0, 0, F@_1, F@_2, TrUserData); - 18 -> d_field_pub_content(Rest, 0, 0, 0, F@_1, F@_2, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_pub(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 1 -> skip_64_pub(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 2 -> skip_length_delimited_pub(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 3 -> skip_group_pub(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 5 -> skip_32_pub(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData) - end - end; -dg_read_field_def_pub(<<>>, 0, 0, _, F@_1, F@_2, _) -> #pub{topic = F@_1, content = F@_2}. - -d_field_pub_topic(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> d_field_pub_topic(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -d_field_pub_topic(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_pub(RestF, 0, 0, F, NewFValue, F@_2, TrUserData). - -d_field_pub_content(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> d_field_pub_content(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -d_field_pub_content(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_pub(RestF, 0, 0, F, F@_1, NewFValue, TrUserData). - -skip_varint_pub(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> skip_varint_pub(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -skip_varint_pub(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_pub(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -skip_length_delimited_pub(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> skip_length_delimited_pub(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -skip_length_delimited_pub(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_pub(Rest2, 0, 0, F, F@_1, F@_2, TrUserData). - -skip_group_pub(Bin, _, Z2, FNum, F@_1, F@_2, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_pub(Rest, 0, Z2, FNum, F@_1, F@_2, TrUserData). - -skip_32_pub(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_pub(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -skip_64_pub(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_pub(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -decode_msg_async_call_reply(Bin, TrUserData) -> dfp_read_field_def_async_call_reply(Bin, 0, 0, 0, id(0, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), TrUserData). - -dfp_read_field_def_async_call_reply(<<8, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_async_call_reply_code(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_async_call_reply(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_async_call_reply_result(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_async_call_reply(<<26, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_async_call_reply_message(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_async_call_reply(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #async_call_reply{code = F@_1, result = F@_2, message = F@_3}; -dfp_read_field_def_async_call_reply(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dg_read_field_def_async_call_reply(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -dg_read_field_def_async_call_reply(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 32 - 7 -> dg_read_field_def_async_call_reply(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -dg_read_field_def_async_call_reply(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 8 -> d_field_async_call_reply_code(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 18 -> d_field_async_call_reply_result(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 26 -> d_field_async_call_reply_message(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_async_call_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 1 -> skip_64_async_call_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 2 -> skip_length_delimited_async_call_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 3 -> skip_group_async_call_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 5 -> skip_32_async_call_reply(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData) - end - end; -dg_read_field_def_async_call_reply(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #async_call_reply{code = F@_1, result = F@_2, message = F@_3}. - -d_field_async_call_reply_code(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_async_call_reply_code(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_async_call_reply_code(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_async_call_reply(RestF, 0, 0, F, NewFValue, F@_2, F@_3, TrUserData). - -d_field_async_call_reply_result(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_async_call_reply_result(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_async_call_reply_result(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_async_call_reply(RestF, 0, 0, F, F@_1, NewFValue, F@_3, TrUserData). - -d_field_async_call_reply_message(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_async_call_reply_message(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_async_call_reply_message(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_async_call_reply(RestF, 0, 0, F, F@_1, F@_2, NewFValue, TrUserData). - -skip_varint_async_call_reply(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> skip_varint_async_call_reply(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -skip_varint_async_call_reply(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_async_call_reply(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_length_delimited_async_call_reply(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> skip_length_delimited_async_call_reply(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -skip_length_delimited_async_call_reply(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_async_call_reply(Rest2, 0, 0, F, F@_1, F@_2, F@_3, TrUserData). - -skip_group_async_call_reply(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_async_call_reply(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, TrUserData). - -skip_32_async_call_reply(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_async_call_reply(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_64_async_call_reply(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_async_call_reply(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -decode_msg_deploy(Bin, TrUserData) -> dfp_read_field_def_deploy(Bin, 0, 0, 0, id(0, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), TrUserData). - -dfp_read_field_def_deploy(<<8, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_deploy_task_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_deploy(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_deploy_service_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_deploy(<<26, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_deploy_tar_url(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_deploy(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #deploy{task_id = F@_1, service_id = F@_2, tar_url = F@_3}; -dfp_read_field_def_deploy(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dg_read_field_def_deploy(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -dg_read_field_def_deploy(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 32 - 7 -> dg_read_field_def_deploy(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -dg_read_field_def_deploy(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 8 -> d_field_deploy_task_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 18 -> d_field_deploy_service_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 26 -> d_field_deploy_tar_url(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_deploy(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 1 -> skip_64_deploy(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 2 -> skip_length_delimited_deploy(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 3 -> skip_group_deploy(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 5 -> skip_32_deploy(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData) - end - end; -dg_read_field_def_deploy(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #deploy{task_id = F@_1, service_id = F@_2, tar_url = F@_3}. - -d_field_deploy_task_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_deploy_task_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_deploy_task_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_deploy(RestF, 0, 0, F, NewFValue, F@_2, F@_3, TrUserData). - -d_field_deploy_service_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_deploy_service_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_deploy_service_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_deploy(RestF, 0, 0, F, F@_1, NewFValue, F@_3, TrUserData). - -d_field_deploy_tar_url(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_deploy_tar_url(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_deploy_tar_url(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_deploy(RestF, 0, 0, F, F@_1, F@_2, NewFValue, TrUserData). - -skip_varint_deploy(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> skip_varint_deploy(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -skip_varint_deploy(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_deploy(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_length_delimited_deploy(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> skip_length_delimited_deploy(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -skip_length_delimited_deploy(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_deploy(Rest2, 0, 0, F, F@_1, F@_2, F@_3, TrUserData). - -skip_group_deploy(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_deploy(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, TrUserData). - -skip_32_deploy(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_deploy(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_64_deploy(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_deploy(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -decode_msg_fetch_task_log(Bin, TrUserData) -> dfp_read_field_def_fetch_task_log(Bin, 0, 0, 0, id(0, TrUserData), TrUserData). - -dfp_read_field_def_fetch_task_log(<<8, Rest/binary>>, Z1, Z2, F, F@_1, TrUserData) -> d_field_fetch_task_log_task_id(Rest, Z1, Z2, F, F@_1, TrUserData); -dfp_read_field_def_fetch_task_log(<<>>, 0, 0, _, F@_1, _) -> #fetch_task_log{task_id = F@_1}; -dfp_read_field_def_fetch_task_log(Other, Z1, Z2, F, F@_1, TrUserData) -> dg_read_field_def_fetch_task_log(Other, Z1, Z2, F, F@_1, TrUserData). - -dg_read_field_def_fetch_task_log(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, TrUserData) when N < 32 - 7 -> dg_read_field_def_fetch_task_log(Rest, N + 7, X bsl N + Acc, F, F@_1, TrUserData); -dg_read_field_def_fetch_task_log(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 8 -> d_field_fetch_task_log_task_id(Rest, 0, 0, 0, F@_1, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_fetch_task_log(Rest, 0, 0, Key bsr 3, F@_1, TrUserData); - 1 -> skip_64_fetch_task_log(Rest, 0, 0, Key bsr 3, F@_1, TrUserData); - 2 -> skip_length_delimited_fetch_task_log(Rest, 0, 0, Key bsr 3, F@_1, TrUserData); - 3 -> skip_group_fetch_task_log(Rest, 0, 0, Key bsr 3, F@_1, TrUserData); - 5 -> skip_32_fetch_task_log(Rest, 0, 0, Key bsr 3, F@_1, TrUserData) - end - end; -dg_read_field_def_fetch_task_log(<<>>, 0, 0, _, F@_1, _) -> #fetch_task_log{task_id = F@_1}. - -d_field_fetch_task_log_task_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, TrUserData) when N < 57 -> d_field_fetch_task_log_task_id(Rest, N + 7, X bsl N + Acc, F, F@_1, TrUserData); -d_field_fetch_task_log_task_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_fetch_task_log(RestF, 0, 0, F, NewFValue, TrUserData). - -skip_varint_fetch_task_log(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, TrUserData) -> skip_varint_fetch_task_log(Rest, Z1, Z2, F, F@_1, TrUserData); -skip_varint_fetch_task_log(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, TrUserData) -> dfp_read_field_def_fetch_task_log(Rest, Z1, Z2, F, F@_1, TrUserData). - -skip_length_delimited_fetch_task_log(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, TrUserData) when N < 57 -> skip_length_delimited_fetch_task_log(Rest, N + 7, X bsl N + Acc, F, F@_1, TrUserData); -skip_length_delimited_fetch_task_log(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_fetch_task_log(Rest2, 0, 0, F, F@_1, TrUserData). - -skip_group_fetch_task_log(Bin, _, Z2, FNum, F@_1, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_fetch_task_log(Rest, 0, Z2, FNum, F@_1, TrUserData). - -skip_32_fetch_task_log(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, TrUserData) -> dfp_read_field_def_fetch_task_log(Rest, Z1, Z2, F, F@_1, TrUserData). - -skip_64_fetch_task_log(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, TrUserData) -> dfp_read_field_def_fetch_task_log(Rest, Z1, Z2, F, F@_1, TrUserData). - -decode_msg_invoke(Bin, TrUserData) -> dfp_read_field_def_invoke(Bin, 0, 0, 0, id(<<>>, TrUserData), id(<<>>, TrUserData), id(0, TrUserData), TrUserData). - -dfp_read_field_def_invoke(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_invoke_service_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_invoke(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_invoke_payload(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_invoke(<<24, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_invoke_timeout(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_invoke(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #invoke{service_id = F@_1, payload = F@_2, timeout = F@_3}; -dfp_read_field_def_invoke(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dg_read_field_def_invoke(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -dg_read_field_def_invoke(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 32 - 7 -> dg_read_field_def_invoke(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -dg_read_field_def_invoke(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_invoke_service_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 18 -> d_field_invoke_payload(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 24 -> d_field_invoke_timeout(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_invoke(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 1 -> skip_64_invoke(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 2 -> skip_length_delimited_invoke(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 3 -> skip_group_invoke(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 5 -> skip_32_invoke(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData) - end - end; -dg_read_field_def_invoke(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #invoke{service_id = F@_1, payload = F@_2, timeout = F@_3}. - -d_field_invoke_service_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_invoke_service_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_invoke_service_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_invoke(RestF, 0, 0, F, NewFValue, F@_2, F@_3, TrUserData). - -d_field_invoke_payload(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_invoke_payload(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_invoke_payload(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_invoke(RestF, 0, 0, F, F@_1, NewFValue, F@_3, TrUserData). - -d_field_invoke_timeout(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_invoke_timeout(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_invoke_timeout(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_invoke(RestF, 0, 0, F, F@_1, F@_2, NewFValue, TrUserData). - -skip_varint_invoke(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> skip_varint_invoke(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -skip_varint_invoke(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_invoke(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_length_delimited_invoke(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> skip_length_delimited_invoke(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -skip_length_delimited_invoke(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_invoke(Rest2, 0, 0, F, F@_1, F@_2, F@_3, TrUserData). - -skip_group_invoke(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_invoke(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, TrUserData). - -skip_32_invoke(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_invoke(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_64_invoke(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_invoke(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -decode_msg_push_service_config(Bin, TrUserData) -> dfp_read_field_def_push_service_config(Bin, 0, 0, 0, id(<<>>, TrUserData), id(<<>>, TrUserData), id(0, TrUserData), TrUserData). - -dfp_read_field_def_push_service_config(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_push_service_config_service_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_push_service_config(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_push_service_config_config_json(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_push_service_config(<<24, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_push_service_config_timeout(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_push_service_config(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #push_service_config{service_id = F@_1, config_json = F@_2, timeout = F@_3}; -dfp_read_field_def_push_service_config(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dg_read_field_def_push_service_config(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -dg_read_field_def_push_service_config(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 32 - 7 -> dg_read_field_def_push_service_config(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -dg_read_field_def_push_service_config(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_push_service_config_service_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 18 -> d_field_push_service_config_config_json(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 24 -> d_field_push_service_config_timeout(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_push_service_config(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 1 -> skip_64_push_service_config(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 2 -> skip_length_delimited_push_service_config(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 3 -> skip_group_push_service_config(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 5 -> skip_32_push_service_config(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData) - end - end; -dg_read_field_def_push_service_config(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #push_service_config{service_id = F@_1, config_json = F@_2, timeout = F@_3}. - -d_field_push_service_config_service_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_push_service_config_service_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_push_service_config_service_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_push_service_config(RestF, 0, 0, F, NewFValue, F@_2, F@_3, TrUserData). - -d_field_push_service_config_config_json(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_push_service_config_config_json(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_push_service_config_config_json(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_push_service_config(RestF, 0, 0, F, F@_1, NewFValue, F@_3, TrUserData). - -d_field_push_service_config_timeout(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_push_service_config_timeout(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_push_service_config_timeout(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_push_service_config(RestF, 0, 0, F, F@_1, F@_2, NewFValue, TrUserData). - -skip_varint_push_service_config(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> skip_varint_push_service_config(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -skip_varint_push_service_config(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_push_service_config(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_length_delimited_push_service_config(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> skip_length_delimited_push_service_config(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -skip_length_delimited_push_service_config(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_push_service_config(Rest2, 0, 0, F, F@_1, F@_2, F@_3, TrUserData). - -skip_group_push_service_config(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_push_service_config(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, TrUserData). - -skip_32_push_service_config(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_push_service_config(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_64_push_service_config(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_push_service_config(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -decode_msg_data(Bin, TrUserData) -> dfp_read_field_def_data(Bin, 0, 0, 0, id(<<>>, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), TrUserData). - -dfp_read_field_def_data(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_data_service_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_data(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_data_device_uuid(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_data(<<26, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_data_route_key(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_data(<<34, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_data_metric(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_data(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, _) -> #data{service_id = F@_1, device_uuid = F@_2, route_key = F@_3, metric = F@_4}; -dfp_read_field_def_data(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dg_read_field_def_data(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -dg_read_field_def_data(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 32 - 7 -> dg_read_field_def_data(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dg_read_field_def_data(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, F@_4, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_data_service_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 18 -> d_field_data_device_uuid(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 26 -> d_field_data_route_key(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 34 -> d_field_data_metric(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_data(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 1 -> skip_64_data(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 2 -> skip_length_delimited_data(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 3 -> skip_group_data(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 5 -> skip_32_data(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData) - end - end; -dg_read_field_def_data(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, _) -> #data{service_id = F@_1, device_uuid = F@_2, route_key = F@_3, metric = F@_4}. - -d_field_data_service_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_data_service_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_data_service_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, F@_4, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_data(RestF, 0, 0, F, NewFValue, F@_2, F@_3, F@_4, TrUserData). - -d_field_data_device_uuid(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_data_device_uuid(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_data_device_uuid(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, F@_4, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_data(RestF, 0, 0, F, F@_1, NewFValue, F@_3, F@_4, TrUserData). - -d_field_data_route_key(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_data_route_key(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_data_route_key(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, F@_4, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_data(RestF, 0, 0, F, F@_1, F@_2, NewFValue, F@_4, TrUserData). - -d_field_data_metric(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_data_metric(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_data_metric(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, _, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_data(RestF, 0, 0, F, F@_1, F@_2, F@_3, NewFValue, TrUserData). - -skip_varint_data(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> skip_varint_data(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -skip_varint_data(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_data(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -skip_length_delimited_data(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> skip_length_delimited_data(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -skip_length_delimited_data(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_data(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -skip_group_data(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, F@_4, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_data(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, F@_4, TrUserData). - -skip_32_data(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_data(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -skip_64_data(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_data(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -decode_msg_ping(Bin, TrUserData) -> - dfp_read_field_def_ping(Bin, - 0, - 0, - 0, - id(<<>>, TrUserData), - id(0, TrUserData), - id(<<>>, TrUserData), - id(<<>>, TrUserData), - id(<<>>, TrUserData), - id(<<>>, TrUserData), - id([], TrUserData), - id(0, TrUserData), - id(0, TrUserData), - id(0.0, TrUserData), - id([], TrUserData), - id([], TrUserData), - id(<<>>, TrUserData), - TrUserData). - -dfp_read_field_def_ping(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_adcode(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<16, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_boot_time(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<26, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_province(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<34, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_city(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<42, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_efka_version(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<50, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_kernel_arch(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<58, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_ips(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_cpu_core(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<72, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_cpu_load(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<85, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_cpu_temperature(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<90, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_pfield_ping_disk(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<88, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_disk(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<98, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_pfield_ping_memory(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<96, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_memory(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<106, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - d_field_ping_interfaces(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dfp_read_field_def_ping(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, R1, F@_8, F@_9, F@_10, R2, R3, F@_13, TrUserData) -> - #ping{adcode = F@_1, boot_time = F@_2, province = F@_3, city = F@_4, efka_version = F@_5, kernel_arch = F@_6, ips = lists_reverse(R1, TrUserData), cpu_core = F@_8, cpu_load = F@_9, cpu_temperature = F@_10, disk = lists_reverse(R2, TrUserData), - memory = lists_reverse(R3, TrUserData), interfaces = F@_13}; -dfp_read_field_def_ping(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - dg_read_field_def_ping(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -dg_read_field_def_ping(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 32 - 7 -> - dg_read_field_def_ping(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -dg_read_field_def_ping(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_ping_adcode(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 16 -> d_field_ping_boot_time(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 26 -> d_field_ping_province(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 34 -> d_field_ping_city(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 42 -> d_field_ping_efka_version(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 50 -> d_field_ping_kernel_arch(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 58 -> d_field_ping_ips(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 64 -> d_field_ping_cpu_core(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 72 -> d_field_ping_cpu_load(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 85 -> d_field_ping_cpu_temperature(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 90 -> d_pfield_ping_disk(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 88 -> d_field_ping_disk(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 98 -> d_pfield_ping_memory(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 96 -> d_field_ping_memory(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 106 -> d_field_ping_interfaces(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_ping(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 1 -> skip_64_ping(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 2 -> skip_length_delimited_ping(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 3 -> skip_group_ping(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); - 5 -> skip_32_ping(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) - end - end; -dg_read_field_def_ping(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, R1, F@_8, F@_9, F@_10, R2, R3, F@_13, TrUserData) -> - #ping{adcode = F@_1, boot_time = F@_2, province = F@_3, city = F@_4, efka_version = F@_5, kernel_arch = F@_6, ips = lists_reverse(R1, TrUserData), cpu_core = F@_8, cpu_load = F@_9, cpu_temperature = F@_10, disk = lists_reverse(R2, TrUserData), - memory = lists_reverse(R3, TrUserData), interfaces = F@_13}. - -d_field_ping_adcode(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_adcode(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_adcode(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_ping(RestF, 0, 0, F, NewFValue, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_boot_time(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_boot_time(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_boot_time(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, NewFValue, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_province(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_province(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_province(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, NewFValue, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_city(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_city(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_city(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, _, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, NewFValue, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_efka_version(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_efka_version(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_efka_version(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, _, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, NewFValue, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_kernel_arch(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_kernel_arch(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_kernel_arch(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, _, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, NewFValue, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_ips(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_ips(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_ips(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, Prev, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, cons(NewFValue, Prev, TrUserData), F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_cpu_core(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_cpu_core(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_cpu_core(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, _, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, NewFValue, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_cpu_load(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_cpu_load(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_cpu_load(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, _, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, NewFValue, F@_10, F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_cpu_temperature(<<0:16, 128, 127, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, _, F@_11, F@_12, F@_13, TrUserData) -> - dfp_read_field_def_ping(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, id(infinity, TrUserData), F@_11, F@_12, F@_13, TrUserData); -d_field_ping_cpu_temperature(<<0:16, 128, 255, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, _, F@_11, F@_12, F@_13, TrUserData) -> - dfp_read_field_def_ping(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, id('-infinity', TrUserData), F@_11, F@_12, F@_13, TrUserData); -d_field_ping_cpu_temperature(<<_:16, 1:1, _:7, _:1, 127:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, _, F@_11, F@_12, F@_13, TrUserData) -> - dfp_read_field_def_ping(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, id(nan, TrUserData), F@_11, F@_12, F@_13, TrUserData); -d_field_ping_cpu_temperature(<>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, _, F@_11, F@_12, F@_13, TrUserData) -> - dfp_read_field_def_ping(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, id(Value, TrUserData), F@_11, F@_12, F@_13, TrUserData). - -d_field_ping_disk(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_disk(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_disk(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, Prev, F@_12, F@_13, TrUserData) -> - {NewFValue, RestF} = {begin <> = <<(X bsl N + Acc):32/unsigned-native>>, id(Res, TrUserData) end, Rest}, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, cons(NewFValue, Prev, TrUserData), F@_12, F@_13, TrUserData). - -d_pfield_ping_disk(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_pfield_ping_disk(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_pfield_ping_disk(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, E, F@_12, F@_13, TrUserData) -> - Len = X bsl N + Acc, - <> = Rest, - NewSeq = d_packed_field_ping_disk(PackedBytes, 0, 0, F, E, TrUserData), - dfp_read_field_def_ping(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, NewSeq, F@_12, F@_13, TrUserData). - -d_packed_field_ping_disk(<<1:1, X:7, Rest/binary>>, N, Acc, F, AccSeq, TrUserData) when N < 57 -> d_packed_field_ping_disk(Rest, N + 7, X bsl N + Acc, F, AccSeq, TrUserData); -d_packed_field_ping_disk(<<0:1, X:7, Rest/binary>>, N, Acc, F, AccSeq, TrUserData) -> - {NewFValue, RestF} = {begin <> = <<(X bsl N + Acc):32/unsigned-native>>, id(Res, TrUserData) end, Rest}, - d_packed_field_ping_disk(RestF, 0, 0, F, [NewFValue | AccSeq], TrUserData); -d_packed_field_ping_disk(<<>>, 0, 0, _, AccSeq, _) -> AccSeq. - -d_field_ping_memory(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_memory(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_memory(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, Prev, F@_13, TrUserData) -> - {NewFValue, RestF} = {begin <> = <<(X bsl N + Acc):32/unsigned-native>>, id(Res, TrUserData) end, Rest}, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, cons(NewFValue, Prev, TrUserData), F@_13, TrUserData). - -d_pfield_ping_memory(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_pfield_ping_memory(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_pfield_ping_memory(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, E, F@_13, TrUserData) -> - Len = X bsl N + Acc, - <> = Rest, - NewSeq = d_packed_field_ping_memory(PackedBytes, 0, 0, F, E, TrUserData), - dfp_read_field_def_ping(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, NewSeq, F@_13, TrUserData). - -d_packed_field_ping_memory(<<1:1, X:7, Rest/binary>>, N, Acc, F, AccSeq, TrUserData) when N < 57 -> d_packed_field_ping_memory(Rest, N + 7, X bsl N + Acc, F, AccSeq, TrUserData); -d_packed_field_ping_memory(<<0:1, X:7, Rest/binary>>, N, Acc, F, AccSeq, TrUserData) -> - {NewFValue, RestF} = {begin <> = <<(X bsl N + Acc):32/unsigned-native>>, id(Res, TrUserData) end, Rest}, - d_packed_field_ping_memory(RestF, 0, 0, F, [NewFValue | AccSeq], TrUserData); -d_packed_field_ping_memory(<<>>, 0, 0, _, AccSeq, _) -> AccSeq. - -d_field_ping_interfaces(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - d_field_ping_interfaces(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -d_field_ping_interfaces(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, _, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_ping(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, NewFValue, TrUserData). - -skip_varint_ping(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - skip_varint_ping(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -skip_varint_ping(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - dfp_read_field_def_ping(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -skip_length_delimited_ping(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) when N < 57 -> - skip_length_delimited_ping(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData); -skip_length_delimited_ping(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_ping(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -skip_group_ping(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_ping(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -skip_32_ping(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - dfp_read_field_def_ping(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -skip_64_ping(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData) -> - dfp_read_field_def_ping(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, F@_9, F@_10, F@_11, F@_12, F@_13, TrUserData). - -decode_msg_service_inform(Bin, TrUserData) -> dfp_read_field_def_service_inform(Bin, 0, 0, 0, id(<<>>, TrUserData), id(<<>>, TrUserData), id(0, TrUserData), id(0, TrUserData), TrUserData). - -dfp_read_field_def_service_inform(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_service_inform_service_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_service_inform(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_service_inform_props(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_service_inform(<<24, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_service_inform_status(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_service_inform(<<32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_service_inform_timestamp(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_service_inform(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, _) -> #service_inform{service_id = F@_1, props = F@_2, status = F@_3, timestamp = F@_4}; -dfp_read_field_def_service_inform(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dg_read_field_def_service_inform(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -dg_read_field_def_service_inform(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 32 - 7 -> dg_read_field_def_service_inform(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dg_read_field_def_service_inform(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, F@_4, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_service_inform_service_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 18 -> d_field_service_inform_props(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 24 -> d_field_service_inform_status(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 32 -> d_field_service_inform_timestamp(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_service_inform(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 1 -> skip_64_service_inform(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 2 -> skip_length_delimited_service_inform(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 3 -> skip_group_service_inform(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 5 -> skip_32_service_inform(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData) - end - end; -dg_read_field_def_service_inform(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, _) -> #service_inform{service_id = F@_1, props = F@_2, status = F@_3, timestamp = F@_4}. - -d_field_service_inform_service_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_service_inform_service_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_service_inform_service_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, F@_4, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_service_inform(RestF, 0, 0, F, NewFValue, F@_2, F@_3, F@_4, TrUserData). - -d_field_service_inform_props(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_service_inform_props(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_service_inform_props(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, F@_4, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_service_inform(RestF, 0, 0, F, F@_1, NewFValue, F@_3, F@_4, TrUserData). - -d_field_service_inform_status(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_service_inform_status(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_service_inform_status(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, F@_4, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_service_inform(RestF, 0, 0, F, F@_1, F@_2, NewFValue, F@_4, TrUserData). - -d_field_service_inform_timestamp(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_service_inform_timestamp(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_service_inform_timestamp(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, _, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_service_inform(RestF, 0, 0, F, F@_1, F@_2, F@_3, NewFValue, TrUserData). - -skip_varint_service_inform(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> skip_varint_service_inform(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -skip_varint_service_inform(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_service_inform(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -skip_length_delimited_service_inform(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> skip_length_delimited_service_inform(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -skip_length_delimited_service_inform(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_service_inform(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -skip_group_service_inform(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, F@_4, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_service_inform(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, F@_4, TrUserData). - -skip_32_service_inform(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_service_inform(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -skip_64_service_inform(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_service_inform(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). - -decode_msg_event(Bin, TrUserData) -> dfp_read_field_def_event(Bin, 0, 0, 0, id(<<>>, TrUserData), id(0, TrUserData), id(<<>>, TrUserData), TrUserData). - -dfp_read_field_def_event(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_event_service_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_event(<<16, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_event_event_type(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_event(<<26, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> d_field_event_params(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -dfp_read_field_def_event(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #event{service_id = F@_1, event_type = F@_2, params = F@_3}; -dfp_read_field_def_event(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dg_read_field_def_event(Other, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -dg_read_field_def_event(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 32 - 7 -> dg_read_field_def_event(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -dg_read_field_def_event(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_event_service_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 16 -> d_field_event_event_type(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - 26 -> d_field_event_params(Rest, 0, 0, 0, F@_1, F@_2, F@_3, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_event(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 1 -> skip_64_event(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 2 -> skip_length_delimited_event(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 3 -> skip_group_event(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData); - 5 -> skip_32_event(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, TrUserData) - end - end; -dg_read_field_def_event(<<>>, 0, 0, _, F@_1, F@_2, F@_3, _) -> #event{service_id = F@_1, event_type = F@_2, params = F@_3}. - -d_field_event_service_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_event_service_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_event_service_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_event(RestF, 0, 0, F, NewFValue, F@_2, F@_3, TrUserData). - -d_field_event_event_type(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_event_event_type(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_event_event_type(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, TrUserData) -> - {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_event(RestF, 0, 0, F, F@_1, NewFValue, F@_3, TrUserData). - -d_field_event_params(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> d_field_event_params(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -d_field_event_params(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_event(RestF, 0, 0, F, F@_1, F@_2, NewFValue, TrUserData). - -skip_varint_event(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> skip_varint_event(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData); -skip_varint_event(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_event(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_length_delimited_event(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) when N < 57 -> skip_length_delimited_event(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, TrUserData); -skip_length_delimited_event(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_event(Rest2, 0, 0, F, F@_1, F@_2, F@_3, TrUserData). - -skip_group_event(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_event(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, TrUserData). - -skip_32_event(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_event(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -skip_64_event(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData) -> dfp_read_field_def_event(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, TrUserData). - -decode_msg_alarm(Bin, TrUserData) -> dfp_read_field_def_alarm(Bin, 0, 0, 0, id(<<>>, TrUserData), id(<<>>, TrUserData), TrUserData). - -dfp_read_field_def_alarm(<<10, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> d_field_alarm_service_id(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -dfp_read_field_def_alarm(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> d_field_alarm_params(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -dfp_read_field_def_alarm(<<>>, 0, 0, _, F@_1, F@_2, _) -> #alarm{service_id = F@_1, params = F@_2}; -dfp_read_field_def_alarm(Other, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dg_read_field_def_alarm(Other, Z1, Z2, F, F@_1, F@_2, TrUserData). - -dg_read_field_def_alarm(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 32 - 7 -> dg_read_field_def_alarm(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -dg_read_field_def_alarm(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, TrUserData) -> - Key = X bsl N + Acc, - case Key of - 10 -> d_field_alarm_service_id(Rest, 0, 0, 0, F@_1, F@_2, TrUserData); - 18 -> d_field_alarm_params(Rest, 0, 0, 0, F@_1, F@_2, TrUserData); - _ -> - case Key band 7 of - 0 -> skip_varint_alarm(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 1 -> skip_64_alarm(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 2 -> skip_length_delimited_alarm(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 3 -> skip_group_alarm(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData); - 5 -> skip_32_alarm(Rest, 0, 0, Key bsr 3, F@_1, F@_2, TrUserData) - end - end; -dg_read_field_def_alarm(<<>>, 0, 0, _, F@_1, F@_2, _) -> #alarm{service_id = F@_1, params = F@_2}. - -d_field_alarm_service_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> d_field_alarm_service_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -d_field_alarm_service_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_alarm(RestF, 0, 0, F, NewFValue, F@_2, TrUserData). - -d_field_alarm_params(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> d_field_alarm_params(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -d_field_alarm_params(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, TrUserData) -> - {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_alarm(RestF, 0, 0, F, F@_1, NewFValue, TrUserData). - -skip_varint_alarm(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> skip_varint_alarm(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData); -skip_varint_alarm(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_alarm(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -skip_length_delimited_alarm(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) when N < 57 -> skip_length_delimited_alarm(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, TrUserData); -skip_length_delimited_alarm(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, TrUserData) -> - Length = X bsl N + Acc, - <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_alarm(Rest2, 0, 0, F, F@_1, F@_2, TrUserData). - -skip_group_alarm(Bin, _, Z2, FNum, F@_1, F@_2, TrUserData) -> - {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_alarm(Rest, 0, Z2, FNum, F@_1, F@_2, TrUserData). - -skip_32_alarm(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_alarm(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -skip_64_alarm(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_alarm(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). - -read_group(Bin, FieldNum) -> - {NumBytes, EndTagLen} = read_gr_b(Bin, 0, 0, 0, 0, FieldNum), - <> = Bin, - {Group, Rest}. - -%% Like skipping over fields, but record the total length, -%% Each field is <(FieldNum bsl 3) bor FieldType> ++ -%% Record the length because varints may be non-optimally encoded. -%% -%% Groups can be nested, but assume the same FieldNum cannot be nested -%% because group field numbers are shared with the rest of the fields -%% numbers. Thus we can search just for an group-end with the same -%% field number. -%% -%% (The only time the same group field number could occur would -%% be in a nested sub message, but then it would be inside a -%% length-delimited entry, which we skip-read by length.) -read_gr_b(<<1:1, X:7, Tl/binary>>, N, Acc, NumBytes, TagLen, FieldNum) - when N < (32-7) -> - read_gr_b(Tl, N+7, X bsl N + Acc, NumBytes, TagLen+1, FieldNum); -read_gr_b(<<0:1, X:7, Tl/binary>>, N, Acc, NumBytes, TagLen, - FieldNum) -> - Key = X bsl N + Acc, - TagLen1 = TagLen + 1, - case {Key bsr 3, Key band 7} of - {FieldNum, 4} -> % 4 = group_end - {NumBytes, TagLen1}; - {_, 0} -> % 0 = varint - read_gr_vi(Tl, 0, NumBytes + TagLen1, FieldNum); - {_, 1} -> % 1 = bits64 - <<_:64, Tl2/binary>> = Tl, - read_gr_b(Tl2, 0, 0, NumBytes + TagLen1 + 8, 0, FieldNum); - {_, 2} -> % 2 = length_delimited - read_gr_ld(Tl, 0, 0, NumBytes + TagLen1, FieldNum); - {_, 3} -> % 3 = group_start - read_gr_b(Tl, 0, 0, NumBytes + TagLen1, 0, FieldNum); - {_, 4} -> % 4 = group_end - read_gr_b(Tl, 0, 0, NumBytes + TagLen1, 0, FieldNum); - {_, 5} -> % 5 = bits32 - <<_:32, Tl2/binary>> = Tl, - read_gr_b(Tl2, 0, 0, NumBytes + TagLen1 + 4, 0, FieldNum) - end. - -read_gr_vi(<<1:1, _:7, Tl/binary>>, N, NumBytes, FieldNum) - when N < (64-7) -> - read_gr_vi(Tl, N+7, NumBytes+1, FieldNum); -read_gr_vi(<<0:1, _:7, Tl/binary>>, _, NumBytes, FieldNum) -> - read_gr_b(Tl, 0, 0, NumBytes+1, 0, FieldNum). - -read_gr_ld(<<1:1, X:7, Tl/binary>>, N, Acc, NumBytes, FieldNum) - when N < (64-7) -> - read_gr_ld(Tl, N+7, X bsl N + Acc, NumBytes+1, FieldNum); -read_gr_ld(<<0:1, X:7, Tl/binary>>, N, Acc, NumBytes, FieldNum) -> - Len = X bsl N + Acc, - NumBytes1 = NumBytes + 1, - <<_:Len/binary, Tl2/binary>> = Tl, - read_gr_b(Tl2, 0, 0, NumBytes1 + Len, 0, FieldNum). - -merge_msgs(Prev, New) when element(1, Prev) =:= element(1, New) -> merge_msgs(Prev, New, element(1, Prev), []). - -merge_msgs(Prev, New, MsgName) when is_atom(MsgName) -> merge_msgs(Prev, New, MsgName, []); -merge_msgs(Prev, New, Opts) when element(1, Prev) =:= element(1, New), is_list(Opts) -> merge_msgs(Prev, New, element(1, Prev), Opts). - -merge_msgs(Prev, New, MsgName, Opts) -> - TrUserData = proplists:get_value(user_data, Opts), - case MsgName of - auth_request -> merge_msg_auth_request(Prev, New, TrUserData); - auth_reply -> merge_msg_auth_reply(Prev, New, TrUserData); - pub -> merge_msg_pub(Prev, New, TrUserData); - async_call_reply -> merge_msg_async_call_reply(Prev, New, TrUserData); - deploy -> merge_msg_deploy(Prev, New, TrUserData); - fetch_task_log -> merge_msg_fetch_task_log(Prev, New, TrUserData); - invoke -> merge_msg_invoke(Prev, New, TrUserData); - push_service_config -> merge_msg_push_service_config(Prev, New, TrUserData); - data -> merge_msg_data(Prev, New, TrUserData); - ping -> merge_msg_ping(Prev, New, TrUserData); - service_inform -> merge_msg_service_inform(Prev, New, TrUserData); - event -> merge_msg_event(Prev, New, TrUserData); - alarm -> merge_msg_alarm(Prev, New, TrUserData) - end. - --compile({nowarn_unused_function,merge_msg_auth_request/3}). -merge_msg_auth_request(#auth_request{uuid = PFuuid, username = PFusername, salt = PFsalt, token = PFtoken, timestamp = PFtimestamp}, #auth_request{uuid = NFuuid, username = NFusername, salt = NFsalt, token = NFtoken, timestamp = NFtimestamp}, _) -> - #auth_request{uuid = - if NFuuid =:= undefined -> PFuuid; - true -> NFuuid - end, - username = - if NFusername =:= undefined -> PFusername; - true -> NFusername - end, - salt = - if NFsalt =:= undefined -> PFsalt; - true -> NFsalt - end, - token = - if NFtoken =:= undefined -> PFtoken; - true -> NFtoken - end, - timestamp = - if NFtimestamp =:= undefined -> PFtimestamp; - true -> NFtimestamp - end}. - --compile({nowarn_unused_function,merge_msg_auth_reply/3}). -merge_msg_auth_reply(#auth_reply{code = PFcode, message = PFmessage}, #auth_reply{code = NFcode, message = NFmessage}, _) -> - #auth_reply{code = - if NFcode =:= undefined -> PFcode; - true -> NFcode - end, - message = - if NFmessage =:= undefined -> PFmessage; - true -> NFmessage - end}. - --compile({nowarn_unused_function,merge_msg_pub/3}). -merge_msg_pub(#pub{topic = PFtopic, content = PFcontent}, #pub{topic = NFtopic, content = NFcontent}, _) -> - #pub{topic = - if NFtopic =:= undefined -> PFtopic; - true -> NFtopic - end, - content = - if NFcontent =:= undefined -> PFcontent; - true -> NFcontent - end}. - --compile({nowarn_unused_function,merge_msg_async_call_reply/3}). -merge_msg_async_call_reply(#async_call_reply{code = PFcode, result = PFresult, message = PFmessage}, #async_call_reply{code = NFcode, result = NFresult, message = NFmessage}, _) -> - #async_call_reply{code = - if NFcode =:= undefined -> PFcode; - true -> NFcode - end, - result = - if NFresult =:= undefined -> PFresult; - true -> NFresult - end, - message = - if NFmessage =:= undefined -> PFmessage; - true -> NFmessage - end}. - --compile({nowarn_unused_function,merge_msg_deploy/3}). -merge_msg_deploy(#deploy{task_id = PFtask_id, service_id = PFservice_id, tar_url = PFtar_url}, #deploy{task_id = NFtask_id, service_id = NFservice_id, tar_url = NFtar_url}, _) -> - #deploy{task_id = - if NFtask_id =:= undefined -> PFtask_id; - true -> NFtask_id - end, - service_id = - if NFservice_id =:= undefined -> PFservice_id; - true -> NFservice_id - end, - tar_url = - if NFtar_url =:= undefined -> PFtar_url; - true -> NFtar_url - end}. - --compile({nowarn_unused_function,merge_msg_fetch_task_log/3}). -merge_msg_fetch_task_log(#fetch_task_log{task_id = PFtask_id}, #fetch_task_log{task_id = NFtask_id}, _) -> - #fetch_task_log{task_id = - if NFtask_id =:= undefined -> PFtask_id; - true -> NFtask_id - end}. - --compile({nowarn_unused_function,merge_msg_invoke/3}). -merge_msg_invoke(#invoke{service_id = PFservice_id, payload = PFpayload, timeout = PFtimeout}, #invoke{service_id = NFservice_id, payload = NFpayload, timeout = NFtimeout}, _) -> - #invoke{service_id = - if NFservice_id =:= undefined -> PFservice_id; - true -> NFservice_id - end, - payload = - if NFpayload =:= undefined -> PFpayload; - true -> NFpayload - end, - timeout = - if NFtimeout =:= undefined -> PFtimeout; - true -> NFtimeout - end}. - --compile({nowarn_unused_function,merge_msg_push_service_config/3}). -merge_msg_push_service_config(#push_service_config{service_id = PFservice_id, config_json = PFconfig_json, timeout = PFtimeout}, #push_service_config{service_id = NFservice_id, config_json = NFconfig_json, timeout = NFtimeout}, _) -> - #push_service_config{service_id = - if NFservice_id =:= undefined -> PFservice_id; - true -> NFservice_id - end, - config_json = - if NFconfig_json =:= undefined -> PFconfig_json; - true -> NFconfig_json - end, - timeout = - if NFtimeout =:= undefined -> PFtimeout; - true -> NFtimeout - end}. - --compile({nowarn_unused_function,merge_msg_data/3}). -merge_msg_data(#data{service_id = PFservice_id, device_uuid = PFdevice_uuid, route_key = PFroute_key, metric = PFmetric}, #data{service_id = NFservice_id, device_uuid = NFdevice_uuid, route_key = NFroute_key, metric = NFmetric}, _) -> - #data{service_id = - if NFservice_id =:= undefined -> PFservice_id; - true -> NFservice_id - end, - device_uuid = - if NFdevice_uuid =:= undefined -> PFdevice_uuid; - true -> NFdevice_uuid - end, - route_key = - if NFroute_key =:= undefined -> PFroute_key; - true -> NFroute_key - end, - metric = - if NFmetric =:= undefined -> PFmetric; - true -> NFmetric - end}. - --compile({nowarn_unused_function,merge_msg_ping/3}). -merge_msg_ping(#ping{adcode = PFadcode, boot_time = PFboot_time, province = PFprovince, city = PFcity, efka_version = PFefka_version, kernel_arch = PFkernel_arch, ips = PFips, cpu_core = PFcpu_core, cpu_load = PFcpu_load, - cpu_temperature = PFcpu_temperature, disk = PFdisk, memory = PFmemory, interfaces = PFinterfaces}, - #ping{adcode = NFadcode, boot_time = NFboot_time, province = NFprovince, city = NFcity, efka_version = NFefka_version, kernel_arch = NFkernel_arch, ips = NFips, cpu_core = NFcpu_core, cpu_load = NFcpu_load, cpu_temperature = NFcpu_temperature, - disk = NFdisk, memory = NFmemory, interfaces = NFinterfaces}, - TrUserData) -> - #ping{adcode = - if NFadcode =:= undefined -> PFadcode; - true -> NFadcode - end, - boot_time = - if NFboot_time =:= undefined -> PFboot_time; - true -> NFboot_time - end, - province = - if NFprovince =:= undefined -> PFprovince; - true -> NFprovince - end, - city = - if NFcity =:= undefined -> PFcity; - true -> NFcity - end, - efka_version = - if NFefka_version =:= undefined -> PFefka_version; - true -> NFefka_version - end, - kernel_arch = - if NFkernel_arch =:= undefined -> PFkernel_arch; - true -> NFkernel_arch - end, - ips = - if PFips /= undefined, NFips /= undefined -> 'erlang_++'(PFips, NFips, TrUserData); - PFips == undefined -> NFips; - NFips == undefined -> PFips - end, - cpu_core = - if NFcpu_core =:= undefined -> PFcpu_core; - true -> NFcpu_core - end, - cpu_load = - if NFcpu_load =:= undefined -> PFcpu_load; - true -> NFcpu_load - end, - cpu_temperature = - if NFcpu_temperature =:= undefined -> PFcpu_temperature; - true -> NFcpu_temperature - end, - disk = - if PFdisk /= undefined, NFdisk /= undefined -> 'erlang_++'(PFdisk, NFdisk, TrUserData); - PFdisk == undefined -> NFdisk; - NFdisk == undefined -> PFdisk - end, - memory = - if PFmemory /= undefined, NFmemory /= undefined -> 'erlang_++'(PFmemory, NFmemory, TrUserData); - PFmemory == undefined -> NFmemory; - NFmemory == undefined -> PFmemory - end, - interfaces = - if NFinterfaces =:= undefined -> PFinterfaces; - true -> NFinterfaces - end}. - --compile({nowarn_unused_function,merge_msg_service_inform/3}). -merge_msg_service_inform(#service_inform{service_id = PFservice_id, props = PFprops, status = PFstatus, timestamp = PFtimestamp}, #service_inform{service_id = NFservice_id, props = NFprops, status = NFstatus, timestamp = NFtimestamp}, _) -> - #service_inform{service_id = - if NFservice_id =:= undefined -> PFservice_id; - true -> NFservice_id - end, - props = - if NFprops =:= undefined -> PFprops; - true -> NFprops - end, - status = - if NFstatus =:= undefined -> PFstatus; - true -> NFstatus - end, - timestamp = - if NFtimestamp =:= undefined -> PFtimestamp; - true -> NFtimestamp - end}. - --compile({nowarn_unused_function,merge_msg_event/3}). -merge_msg_event(#event{service_id = PFservice_id, event_type = PFevent_type, params = PFparams}, #event{service_id = NFservice_id, event_type = NFevent_type, params = NFparams}, _) -> - #event{service_id = - if NFservice_id =:= undefined -> PFservice_id; - true -> NFservice_id - end, - event_type = - if NFevent_type =:= undefined -> PFevent_type; - true -> NFevent_type - end, - params = - if NFparams =:= undefined -> PFparams; - true -> NFparams - end}. - --compile({nowarn_unused_function,merge_msg_alarm/3}). -merge_msg_alarm(#alarm{service_id = PFservice_id, params = PFparams}, #alarm{service_id = NFservice_id, params = NFparams}, _) -> - #alarm{service_id = - if NFservice_id =:= undefined -> PFservice_id; - true -> NFservice_id - end, - params = - if NFparams =:= undefined -> PFparams; - true -> NFparams - end}. - - -verify_msg(Msg) when tuple_size(Msg) >= 1 -> verify_msg(Msg, element(1, Msg), []); -verify_msg(X) -> mk_type_error(not_a_known_message, X, []). - -verify_msg(Msg, MsgName) when is_atom(MsgName) -> verify_msg(Msg, MsgName, []); -verify_msg(Msg, Opts) when tuple_size(Msg) >= 1 -> verify_msg(Msg, element(1, Msg), Opts); -verify_msg(X, _Opts) -> mk_type_error(not_a_known_message, X, []). - -verify_msg(Msg, MsgName, Opts) -> - TrUserData = proplists:get_value(user_data, Opts), - case MsgName of - auth_request -> v_msg_auth_request(Msg, [MsgName], TrUserData); - auth_reply -> v_msg_auth_reply(Msg, [MsgName], TrUserData); - pub -> v_msg_pub(Msg, [MsgName], TrUserData); - async_call_reply -> v_msg_async_call_reply(Msg, [MsgName], TrUserData); - deploy -> v_msg_deploy(Msg, [MsgName], TrUserData); - fetch_task_log -> v_msg_fetch_task_log(Msg, [MsgName], TrUserData); - invoke -> v_msg_invoke(Msg, [MsgName], TrUserData); - push_service_config -> v_msg_push_service_config(Msg, [MsgName], TrUserData); - data -> v_msg_data(Msg, [MsgName], TrUserData); - ping -> v_msg_ping(Msg, [MsgName], TrUserData); - service_inform -> v_msg_service_inform(Msg, [MsgName], TrUserData); - event -> v_msg_event(Msg, [MsgName], TrUserData); - alarm -> v_msg_alarm(Msg, [MsgName], TrUserData); - _ -> mk_type_error(not_a_known_message, Msg, []) - end. - - --compile({nowarn_unused_function,v_msg_auth_request/3}). --dialyzer({nowarn_function,v_msg_auth_request/3}). -v_msg_auth_request(#auth_request{uuid = F1, username = F2, salt = F3, token = F4, timestamp = F5}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [uuid | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_string(F2, [username | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_string(F3, [salt | Path], TrUserData) - end, - if F4 == undefined -> ok; - true -> v_type_string(F4, [token | Path], TrUserData) - end, - if F5 == undefined -> ok; - true -> v_type_uint32(F5, [timestamp | Path], TrUserData) - end, - ok; -v_msg_auth_request(X, Path, _TrUserData) -> mk_type_error({expected_msg, auth_request}, X, Path). - --compile({nowarn_unused_function,v_msg_auth_reply/3}). --dialyzer({nowarn_function,v_msg_auth_reply/3}). -v_msg_auth_reply(#auth_reply{code = F1, message = F2}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_uint32(F1, [code | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_string(F2, [message | Path], TrUserData) - end, - ok; -v_msg_auth_reply(X, Path, _TrUserData) -> mk_type_error({expected_msg, auth_reply}, X, Path). - --compile({nowarn_unused_function,v_msg_pub/3}). --dialyzer({nowarn_function,v_msg_pub/3}). -v_msg_pub(#pub{topic = F1, content = F2}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [topic | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_bytes(F2, [content | Path], TrUserData) - end, - ok; -v_msg_pub(X, Path, _TrUserData) -> mk_type_error({expected_msg, pub}, X, Path). - --compile({nowarn_unused_function,v_msg_async_call_reply/3}). --dialyzer({nowarn_function,v_msg_async_call_reply/3}). -v_msg_async_call_reply(#async_call_reply{code = F1, result = F2, message = F3}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_uint32(F1, [code | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_string(F2, [result | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_string(F3, [message | Path], TrUserData) - end, - ok; -v_msg_async_call_reply(X, Path, _TrUserData) -> mk_type_error({expected_msg, async_call_reply}, X, Path). - --compile({nowarn_unused_function,v_msg_deploy/3}). --dialyzer({nowarn_function,v_msg_deploy/3}). -v_msg_deploy(#deploy{task_id = F1, service_id = F2, tar_url = F3}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_uint32(F1, [task_id | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_string(F2, [service_id | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_string(F3, [tar_url | Path], TrUserData) - end, - ok; -v_msg_deploy(X, Path, _TrUserData) -> mk_type_error({expected_msg, deploy}, X, Path). - --compile({nowarn_unused_function,v_msg_fetch_task_log/3}). --dialyzer({nowarn_function,v_msg_fetch_task_log/3}). -v_msg_fetch_task_log(#fetch_task_log{task_id = F1}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_uint32(F1, [task_id | Path], TrUserData) - end, - ok; -v_msg_fetch_task_log(X, Path, _TrUserData) -> mk_type_error({expected_msg, fetch_task_log}, X, Path). - --compile({nowarn_unused_function,v_msg_invoke/3}). --dialyzer({nowarn_function,v_msg_invoke/3}). -v_msg_invoke(#invoke{service_id = F1, payload = F2, timeout = F3}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [service_id | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_bytes(F2, [payload | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_uint32(F3, [timeout | Path], TrUserData) - end, - ok; -v_msg_invoke(X, Path, _TrUserData) -> mk_type_error({expected_msg, invoke}, X, Path). - --compile({nowarn_unused_function,v_msg_push_service_config/3}). --dialyzer({nowarn_function,v_msg_push_service_config/3}). -v_msg_push_service_config(#push_service_config{service_id = F1, config_json = F2, timeout = F3}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [service_id | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_string(F2, [config_json | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_uint32(F3, [timeout | Path], TrUserData) - end, - ok; -v_msg_push_service_config(X, Path, _TrUserData) -> mk_type_error({expected_msg, push_service_config}, X, Path). - --compile({nowarn_unused_function,v_msg_data/3}). --dialyzer({nowarn_function,v_msg_data/3}). -v_msg_data(#data{service_id = F1, device_uuid = F2, route_key = F3, metric = F4}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [service_id | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_string(F2, [device_uuid | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_string(F3, [route_key | Path], TrUserData) - end, - if F4 == undefined -> ok; - true -> v_type_bytes(F4, [metric | Path], TrUserData) - end, - ok; -v_msg_data(X, Path, _TrUserData) -> mk_type_error({expected_msg, data}, X, Path). - --compile({nowarn_unused_function,v_msg_ping/3}). --dialyzer({nowarn_function,v_msg_ping/3}). -v_msg_ping(#ping{adcode = F1, boot_time = F2, province = F3, city = F4, efka_version = F5, kernel_arch = F6, ips = F7, cpu_core = F8, cpu_load = F9, cpu_temperature = F10, disk = F11, memory = F12, interfaces = F13}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [adcode | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_uint32(F2, [boot_time | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_string(F3, [province | Path], TrUserData) - end, - if F4 == undefined -> ok; - true -> v_type_string(F4, [city | Path], TrUserData) - end, - if F5 == undefined -> ok; - true -> v_type_string(F5, [efka_version | Path], TrUserData) - end, - if F6 == undefined -> ok; - true -> v_type_string(F6, [kernel_arch | Path], TrUserData) - end, - if is_list(F7) -> - _ = [v_type_string(Elem, [ips | Path], TrUserData) || Elem <- F7], - ok; - true -> mk_type_error({invalid_list_of, string}, F7, [ips | Path]) - end, - if F8 == undefined -> ok; - true -> v_type_uint32(F8, [cpu_core | Path], TrUserData) - end, - if F9 == undefined -> ok; - true -> v_type_uint32(F9, [cpu_load | Path], TrUserData) - end, - if F10 == undefined -> ok; - true -> v_type_float(F10, [cpu_temperature | Path], TrUserData) - end, - if is_list(F11) -> - _ = [v_type_int32(Elem, [disk | Path], TrUserData) || Elem <- F11], - ok; - true -> mk_type_error({invalid_list_of, int32}, F11, [disk | Path]) - end, - if is_list(F12) -> - _ = [v_type_int32(Elem, [memory | Path], TrUserData) || Elem <- F12], - ok; - true -> mk_type_error({invalid_list_of, int32}, F12, [memory | Path]) - end, - if F13 == undefined -> ok; - true -> v_type_string(F13, [interfaces | Path], TrUserData) - end, - ok; -v_msg_ping(X, Path, _TrUserData) -> mk_type_error({expected_msg, ping}, X, Path). - --compile({nowarn_unused_function,v_msg_service_inform/3}). --dialyzer({nowarn_function,v_msg_service_inform/3}). -v_msg_service_inform(#service_inform{service_id = F1, props = F2, status = F3, timestamp = F4}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [service_id | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_string(F2, [props | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_uint32(F3, [status | Path], TrUserData) - end, - if F4 == undefined -> ok; - true -> v_type_uint32(F4, [timestamp | Path], TrUserData) - end, - ok; -v_msg_service_inform(X, Path, _TrUserData) -> mk_type_error({expected_msg, service_inform}, X, Path). - --compile({nowarn_unused_function,v_msg_event/3}). --dialyzer({nowarn_function,v_msg_event/3}). -v_msg_event(#event{service_id = F1, event_type = F2, params = F3}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [service_id | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_uint32(F2, [event_type | Path], TrUserData) - end, - if F3 == undefined -> ok; - true -> v_type_string(F3, [params | Path], TrUserData) - end, - ok; -v_msg_event(X, Path, _TrUserData) -> mk_type_error({expected_msg, event}, X, Path). - --compile({nowarn_unused_function,v_msg_alarm/3}). --dialyzer({nowarn_function,v_msg_alarm/3}). -v_msg_alarm(#alarm{service_id = F1, params = F2}, Path, TrUserData) -> - if F1 == undefined -> ok; - true -> v_type_string(F1, [service_id | Path], TrUserData) - end, - if F2 == undefined -> ok; - true -> v_type_string(F2, [params | Path], TrUserData) - end, - ok; -v_msg_alarm(X, Path, _TrUserData) -> mk_type_error({expected_msg, alarm}, X, Path). - --compile({nowarn_unused_function,v_type_int32/3}). --dialyzer({nowarn_function,v_type_int32/3}). -v_type_int32(N, _Path, _TrUserData) when is_integer(N), -2147483648 =< N, N =< 2147483647 -> ok; -v_type_int32(N, Path, _TrUserData) when is_integer(N) -> mk_type_error({value_out_of_range, int32, signed, 32}, N, Path); -v_type_int32(X, Path, _TrUserData) -> mk_type_error({bad_integer, int32, signed, 32}, X, Path). - --compile({nowarn_unused_function,v_type_uint32/3}). --dialyzer({nowarn_function,v_type_uint32/3}). -v_type_uint32(N, _Path, _TrUserData) when is_integer(N), 0 =< N, N =< 4294967295 -> ok; -v_type_uint32(N, Path, _TrUserData) when is_integer(N) -> mk_type_error({value_out_of_range, uint32, unsigned, 32}, N, Path); -v_type_uint32(X, Path, _TrUserData) -> mk_type_error({bad_integer, uint32, unsigned, 32}, X, Path). - --compile({nowarn_unused_function,v_type_float/3}). --dialyzer({nowarn_function,v_type_float/3}). -v_type_float(N, _Path, _TrUserData) when is_float(N) -> ok; -v_type_float(N, _Path, _TrUserData) when is_integer(N) -> ok; -v_type_float(infinity, _Path, _TrUserData) -> ok; -v_type_float('-infinity', _Path, _TrUserData) -> ok; -v_type_float(nan, _Path, _TrUserData) -> ok; -v_type_float(X, Path, _TrUserData) -> mk_type_error(bad_float_value, X, Path). - --compile({nowarn_unused_function,v_type_string/3}). --dialyzer({nowarn_function,v_type_string/3}). -v_type_string(S, Path, _TrUserData) when is_list(S); is_binary(S) -> - try unicode:characters_to_binary(S) of - B when is_binary(B) -> ok; - {error, _, _} -> mk_type_error(bad_unicode_string, S, Path) - catch - error:badarg -> mk_type_error(bad_unicode_string, S, Path) - end; -v_type_string(X, Path, _TrUserData) -> mk_type_error(bad_unicode_string, X, Path). - --compile({nowarn_unused_function,v_type_bytes/3}). --dialyzer({nowarn_function,v_type_bytes/3}). -v_type_bytes(B, _Path, _TrUserData) when is_binary(B) -> ok; -v_type_bytes(B, _Path, _TrUserData) when is_list(B) -> ok; -v_type_bytes(X, Path, _TrUserData) -> mk_type_error(bad_binary_value, X, Path). - --compile({nowarn_unused_function,mk_type_error/3}). --spec mk_type_error(_, _, list()) -> no_return(). -mk_type_error(Error, ValueSeen, Path) -> - Path2 = prettify_path(Path), - erlang:error({gpb_type_error, {Error, [{value, ValueSeen}, {path, Path2}]}}). - - --compile({nowarn_unused_function,prettify_path/1}). --dialyzer({nowarn_function,prettify_path/1}). -prettify_path([]) -> top_level; -prettify_path(PathR) -> lists:append(lists:join(".", lists:map(fun atom_to_list/1, lists:reverse(PathR)))). - - --compile({nowarn_unused_function,id/2}). --compile({inline,id/2}). -id(X, _TrUserData) -> X. - --compile({nowarn_unused_function,v_ok/3}). --compile({inline,v_ok/3}). -v_ok(_Value, _Path, _TrUserData) -> ok. - --compile({nowarn_unused_function,m_overwrite/3}). --compile({inline,m_overwrite/3}). -m_overwrite(_Prev, New, _TrUserData) -> New. - --compile({nowarn_unused_function,cons/3}). --compile({inline,cons/3}). -cons(Elem, Acc, _TrUserData) -> [Elem | Acc]. - --compile({nowarn_unused_function,lists_reverse/2}). --compile({inline,lists_reverse/2}). -'lists_reverse'(L, _TrUserData) -> lists:reverse(L). --compile({nowarn_unused_function,'erlang_++'/3}). --compile({inline,'erlang_++'/3}). -'erlang_++'(A, B, _TrUserData) -> A ++ B. - - -get_msg_defs() -> - [{{msg, auth_request}, - [#field{name = uuid, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = username, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = salt, fnum = 4, rnum = 4, type = string, occurrence = optional, opts = []}, - #field{name = token, fnum = 5, rnum = 5, type = string, occurrence = optional, opts = []}, - #field{name = timestamp, fnum = 6, rnum = 6, type = uint32, occurrence = optional, opts = []}]}, - {{msg, auth_reply}, [#field{name = code, fnum = 1, rnum = 2, type = uint32, occurrence = optional, opts = []}, #field{name = message, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}]}, - {{msg, pub}, [#field{name = topic, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, #field{name = content, fnum = 2, rnum = 3, type = bytes, occurrence = optional, opts = []}]}, - {{msg, async_call_reply}, - [#field{name = code, fnum = 1, rnum = 2, type = uint32, occurrence = optional, opts = []}, - #field{name = result, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = message, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}]}, - {{msg, deploy}, - [#field{name = task_id, fnum = 1, rnum = 2, type = uint32, occurrence = optional, opts = []}, - #field{name = service_id, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = tar_url, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}]}, - {{msg, fetch_task_log}, [#field{name = task_id, fnum = 1, rnum = 2, type = uint32, occurrence = optional, opts = []}]}, - {{msg, invoke}, - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = payload, fnum = 2, rnum = 3, type = bytes, occurrence = optional, opts = []}, - #field{name = timeout, fnum = 3, rnum = 4, type = uint32, occurrence = optional, opts = []}]}, - {{msg, push_service_config}, - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = config_json, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = timeout, fnum = 3, rnum = 4, type = uint32, occurrence = optional, opts = []}]}, - {{msg, data}, - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = device_uuid, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = route_key, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}, - #field{name = metric, fnum = 4, rnum = 5, type = bytes, occurrence = optional, opts = []}]}, - {{msg, ping}, - [#field{name = adcode, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = boot_time, fnum = 2, rnum = 3, type = uint32, occurrence = optional, opts = []}, - #field{name = province, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}, - #field{name = city, fnum = 4, rnum = 5, type = string, occurrence = optional, opts = []}, - #field{name = efka_version, fnum = 5, rnum = 6, type = string, occurrence = optional, opts = []}, - #field{name = kernel_arch, fnum = 6, rnum = 7, type = string, occurrence = optional, opts = []}, - #field{name = ips, fnum = 7, rnum = 8, type = string, occurrence = repeated, opts = []}, - #field{name = cpu_core, fnum = 8, rnum = 9, type = uint32, occurrence = optional, opts = []}, - #field{name = cpu_load, fnum = 9, rnum = 10, type = uint32, occurrence = optional, opts = []}, - #field{name = cpu_temperature, fnum = 10, rnum = 11, type = float, occurrence = optional, opts = []}, - #field{name = disk, fnum = 11, rnum = 12, type = int32, occurrence = repeated, opts = [packed]}, - #field{name = memory, fnum = 12, rnum = 13, type = int32, occurrence = repeated, opts = [packed]}, - #field{name = interfaces, fnum = 13, rnum = 14, type = string, occurrence = optional, opts = []}]}, - {{msg, service_inform}, - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = props, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = status, fnum = 3, rnum = 4, type = uint32, occurrence = optional, opts = []}, - #field{name = timestamp, fnum = 4, rnum = 5, type = uint32, occurrence = optional, opts = []}]}, - {{msg, event}, - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = event_type, fnum = 2, rnum = 3, type = uint32, occurrence = optional, opts = []}, - #field{name = params, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}]}, - {{msg, alarm}, [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, #field{name = params, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}]}]. - - -get_msg_names() -> [auth_request, auth_reply, pub, async_call_reply, deploy, fetch_task_log, invoke, push_service_config, data, ping, service_inform, event, alarm]. - - -get_group_names() -> []. - - -get_msg_or_group_names() -> [auth_request, auth_reply, pub, async_call_reply, deploy, fetch_task_log, invoke, push_service_config, data, ping, service_inform, event, alarm]. - - -get_enum_names() -> []. - - -fetch_msg_def(MsgName) -> - case find_msg_def(MsgName) of - Fs when is_list(Fs) -> Fs; - error -> erlang:error({no_such_msg, MsgName}) - end. - - --spec fetch_enum_def(_) -> no_return(). -fetch_enum_def(EnumName) -> erlang:error({no_such_enum, EnumName}). - - -find_msg_def(auth_request) -> - [#field{name = uuid, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = username, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = salt, fnum = 4, rnum = 4, type = string, occurrence = optional, opts = []}, - #field{name = token, fnum = 5, rnum = 5, type = string, occurrence = optional, opts = []}, - #field{name = timestamp, fnum = 6, rnum = 6, type = uint32, occurrence = optional, opts = []}]; -find_msg_def(auth_reply) -> [#field{name = code, fnum = 1, rnum = 2, type = uint32, occurrence = optional, opts = []}, #field{name = message, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}]; -find_msg_def(pub) -> [#field{name = topic, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, #field{name = content, fnum = 2, rnum = 3, type = bytes, occurrence = optional, opts = []}]; -find_msg_def(async_call_reply) -> - [#field{name = code, fnum = 1, rnum = 2, type = uint32, occurrence = optional, opts = []}, - #field{name = result, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = message, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}]; -find_msg_def(deploy) -> - [#field{name = task_id, fnum = 1, rnum = 2, type = uint32, occurrence = optional, opts = []}, - #field{name = service_id, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = tar_url, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}]; -find_msg_def(fetch_task_log) -> [#field{name = task_id, fnum = 1, rnum = 2, type = uint32, occurrence = optional, opts = []}]; -find_msg_def(invoke) -> - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = payload, fnum = 2, rnum = 3, type = bytes, occurrence = optional, opts = []}, - #field{name = timeout, fnum = 3, rnum = 4, type = uint32, occurrence = optional, opts = []}]; -find_msg_def(push_service_config) -> - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = config_json, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = timeout, fnum = 3, rnum = 4, type = uint32, occurrence = optional, opts = []}]; -find_msg_def(data) -> - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = device_uuid, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = route_key, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}, - #field{name = metric, fnum = 4, rnum = 5, type = bytes, occurrence = optional, opts = []}]; -find_msg_def(ping) -> - [#field{name = adcode, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = boot_time, fnum = 2, rnum = 3, type = uint32, occurrence = optional, opts = []}, - #field{name = province, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}, - #field{name = city, fnum = 4, rnum = 5, type = string, occurrence = optional, opts = []}, - #field{name = efka_version, fnum = 5, rnum = 6, type = string, occurrence = optional, opts = []}, - #field{name = kernel_arch, fnum = 6, rnum = 7, type = string, occurrence = optional, opts = []}, - #field{name = ips, fnum = 7, rnum = 8, type = string, occurrence = repeated, opts = []}, - #field{name = cpu_core, fnum = 8, rnum = 9, type = uint32, occurrence = optional, opts = []}, - #field{name = cpu_load, fnum = 9, rnum = 10, type = uint32, occurrence = optional, opts = []}, - #field{name = cpu_temperature, fnum = 10, rnum = 11, type = float, occurrence = optional, opts = []}, - #field{name = disk, fnum = 11, rnum = 12, type = int32, occurrence = repeated, opts = [packed]}, - #field{name = memory, fnum = 12, rnum = 13, type = int32, occurrence = repeated, opts = [packed]}, - #field{name = interfaces, fnum = 13, rnum = 14, type = string, occurrence = optional, opts = []}]; -find_msg_def(service_inform) -> - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = props, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}, - #field{name = status, fnum = 3, rnum = 4, type = uint32, occurrence = optional, opts = []}, - #field{name = timestamp, fnum = 4, rnum = 5, type = uint32, occurrence = optional, opts = []}]; -find_msg_def(event) -> - [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, - #field{name = event_type, fnum = 2, rnum = 3, type = uint32, occurrence = optional, opts = []}, - #field{name = params, fnum = 3, rnum = 4, type = string, occurrence = optional, opts = []}]; -find_msg_def(alarm) -> [#field{name = service_id, fnum = 1, rnum = 2, type = string, occurrence = optional, opts = []}, #field{name = params, fnum = 2, rnum = 3, type = string, occurrence = optional, opts = []}]; -find_msg_def(_) -> error. - - -find_enum_def(_) -> error. - - --spec enum_symbol_by_value(_, _) -> no_return(). -enum_symbol_by_value(E, V) -> erlang:error({no_enum_defs, E, V}). - - --spec enum_value_by_symbol(_, _) -> no_return(). -enum_value_by_symbol(E, V) -> erlang:error({no_enum_defs, E, V}). - - - -get_service_names() -> []. - - -get_service_def(_) -> error. - - -get_rpc_names(_) -> error. - - -find_rpc_def(_, _) -> error. - - - --spec fetch_rpc_def(_, _) -> no_return(). -fetch_rpc_def(ServiceName, RpcName) -> erlang:error({no_such_rpc, ServiceName, RpcName}). - - -%% Convert a a fully qualified (ie with package name) service name -%% as a binary to a service name as an atom. --spec fqbin_to_service_name(_) -> no_return(). -fqbin_to_service_name(X) -> error({gpb_error, {badservice, X}}). - - -%% Convert a service name as an atom to a fully qualified -%% (ie with package name) name as a binary. --spec service_name_to_fqbin(_) -> no_return(). -service_name_to_fqbin(X) -> error({gpb_error, {badservice, X}}). - - -%% Convert a a fully qualified (ie with package name) service name -%% and an rpc name, both as binaries to a service name and an rpc -%% name, as atoms. --spec fqbins_to_service_and_rpc_name(_, _) -> no_return(). -fqbins_to_service_and_rpc_name(S, R) -> error({gpb_error, {badservice_or_rpc, {S, R}}}). - - -%% Convert a service name and an rpc name, both as atoms, -%% to a fully qualified (ie with package name) service name and -%% an rpc name as binaries. --spec service_and_rpc_name_to_fqbins(_, _) -> no_return(). -service_and_rpc_name_to_fqbins(S, R) -> error({gpb_error, {badservice_or_rpc, {S, R}}}). - - -fqbin_to_msg_name(<<"AuthRequest">>) -> auth_request; -fqbin_to_msg_name(<<"AuthReply">>) -> auth_reply; -fqbin_to_msg_name(<<"Pub">>) -> pub; -fqbin_to_msg_name(<<"AsyncCallReply">>) -> async_call_reply; -fqbin_to_msg_name(<<"Deploy">>) -> deploy; -fqbin_to_msg_name(<<"FetchTaskLog">>) -> fetch_task_log; -fqbin_to_msg_name(<<"Invoke">>) -> invoke; -fqbin_to_msg_name(<<"PushServiceConfig">>) -> push_service_config; -fqbin_to_msg_name(<<"Data">>) -> data; -fqbin_to_msg_name(<<"Ping">>) -> ping; -fqbin_to_msg_name(<<"ServiceInform">>) -> service_inform; -fqbin_to_msg_name(<<"Event">>) -> event; -fqbin_to_msg_name(<<"Alarm">>) -> alarm; -fqbin_to_msg_name(E) -> error({gpb_error, {badmsg, E}}). - - -msg_name_to_fqbin(auth_request) -> <<"AuthRequest">>; -msg_name_to_fqbin(auth_reply) -> <<"AuthReply">>; -msg_name_to_fqbin(pub) -> <<"Pub">>; -msg_name_to_fqbin(async_call_reply) -> <<"AsyncCallReply">>; -msg_name_to_fqbin(deploy) -> <<"Deploy">>; -msg_name_to_fqbin(fetch_task_log) -> <<"FetchTaskLog">>; -msg_name_to_fqbin(invoke) -> <<"Invoke">>; -msg_name_to_fqbin(push_service_config) -> <<"PushServiceConfig">>; -msg_name_to_fqbin(data) -> <<"Data">>; -msg_name_to_fqbin(ping) -> <<"Ping">>; -msg_name_to_fqbin(service_inform) -> <<"ServiceInform">>; -msg_name_to_fqbin(event) -> <<"Event">>; -msg_name_to_fqbin(alarm) -> <<"Alarm">>; -msg_name_to_fqbin(E) -> error({gpb_error, {badmsg, E}}). - - --spec fqbin_to_enum_name(_) -> no_return(). -fqbin_to_enum_name(E) -> error({gpb_error, {badenum, E}}). - - --spec enum_name_to_fqbin(_) -> no_return(). -enum_name_to_fqbin(E) -> error({gpb_error, {badenum, E}}). - - -get_package_name() -> undefined. - - -%% Whether or not the message names -%% are prepended with package name or not. -uses_packages() -> false. - - -source_basename() -> "message_pb.proto". - - -%% Retrieve all proto file names, also imported ones. -%% The order is top-down. The first element is always the main -%% source file. The files are returned with extension, -%% see get_all_proto_names/0 for a version that returns -%% the basenames sans extension -get_all_source_basenames() -> ["message_pb.proto"]. - - -%% Retrieve all proto file names, also imported ones. -%% The order is top-down. The first element is always the main -%% source file. The files are returned sans .proto extension, -%% to make it easier to use them with the various get_xyz_containment -%% functions. -get_all_proto_names() -> ["message_pb"]. - - -get_msg_containment("message_pb") -> [alarm, async_call_reply, auth_reply, auth_request, data, deploy, event, fetch_task_log, invoke, ping, pub, push_service_config, service_inform]; -get_msg_containment(P) -> error({gpb_error, {badproto, P}}). - - -get_pkg_containment("message_pb") -> undefined; -get_pkg_containment(P) -> error({gpb_error, {badproto, P}}). - - -get_service_containment("message_pb") -> []; -get_service_containment(P) -> error({gpb_error, {badproto, P}}). - - -get_rpc_containment("message_pb") -> []; -get_rpc_containment(P) -> error({gpb_error, {badproto, P}}). - - -get_enum_containment("message_pb") -> []; -get_enum_containment(P) -> error({gpb_error, {badproto, P}}). - - -get_proto_by_msg_name_as_fqbin(<<"Data">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"Pub">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"Event">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"AuthRequest">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"Invoke">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"PushServiceConfig">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"Ping">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"FetchTaskLog">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"Deploy">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"AuthReply">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"AsyncCallReply">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"ServiceInform">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(<<"Alarm">>) -> "message_pb"; -get_proto_by_msg_name_as_fqbin(E) -> error({gpb_error, {badmsg, E}}). - - --spec get_proto_by_service_name_as_fqbin(_) -> no_return(). -get_proto_by_service_name_as_fqbin(E) -> error({gpb_error, {badservice, E}}). - - --spec get_proto_by_enum_name_as_fqbin(_) -> no_return(). -get_proto_by_enum_name_as_fqbin(E) -> error({gpb_error, {badenum, E}}). - - --spec get_protos_by_pkg_name_as_fqbin(_) -> no_return(). -get_protos_by_pkg_name_as_fqbin(E) -> error({gpb_error, {badpkg, E}}). - - - -gpb_version_as_string() -> - "4.21.1". - -gpb_version_as_list() -> - [4,21,1]. - -gpb_version_source() -> - "git". diff --git a/apps/iot/src/tcp/tcp_channel.erl b/apps/iot/src/tcp/tcp_channel.erl index caece41..9ceb712 100644 --- a/apps/iot/src/tcp/tcp_channel.erl +++ b/apps/iot/src/tcp/tcp_channel.erl @@ -8,16 +8,15 @@ %%%------------------------------------------------------------------- -module(tcp_channel). -author("licheng5"). --include("iot.hrl"). --include("message_pb.hrl"). +-include("message.hrl"). +-behaviour(ranch_protocol). %% API --export([pub/3, async_call/4, command/3]). --export([stop/2]). +-export([pub/3, jsonrpc_call/3, command/3]). --export([start_link/2]). +-export([start_link/3, stop/2]). %% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]). +-export([init/3, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]). -record(state, { transport, @@ -44,10 +43,10 @@ command(Pid, CommandType, Command) when is_pid(Pid), is_integer(CommandType), is gen_server:cast(Pid, {command, CommandType, Command}). %% 向通道中写入消息 --spec async_call(Pid :: pid(), ReceiverPid :: pid(), CallType :: integer(), CallBin :: binary()) -> Ref :: reference(). -async_call(Pid, ReceiverPid, CallType, CallBin) when is_pid(Pid), is_pid(ReceiverPid), is_integer(CallType), is_binary(CallBin) -> +-spec jsonrpc_call(Pid :: pid(), ReceiverPid :: pid(), CallBin :: binary()) -> Ref :: reference(). +jsonrpc_call(Pid, ReceiverPid, CallBin) when is_pid(Pid), is_pid(ReceiverPid), is_binary(CallBin) -> Ref = make_ref(), - gen_server:cast(Pid, {async_call, ReceiverPid, Ref, CallType, CallBin}), + gen_server:cast(Pid, {jsonrpc_call, ReceiverPid, Ref, CallBin}), Ref. %% 关闭方法 @@ -61,46 +60,43 @@ stop(Pid, Reason) when is_pid(Pid) -> %% 逻辑处理方法 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -start_link(Transport, Sock) -> - {ok, proc_lib:spawn_link(?MODULE, init, [[Transport, Sock]])}. +start_link(Ref, Transport, Opts) -> + {ok, proc_lib:spawn_link(?MODULE, init, [Ref, Transport, Opts])}. -init([Transport, Sock]) -> - lager:debug("[sdlan_channel] get a new connection: ~p", [Sock]), - case Transport:wait(Sock) of - {ok, NewSock} -> - Transport:setopts(Sock, [{active, true}]), - % erlang:start_timer(?PING_TICKER, self(), ping_ticker), - gen_server:enter_loop(?MODULE, [], #state{transport = Transport, socket = NewSock}); - {error, Reason} -> - {stop, Reason} - end. +init(Ref, Transport, _Opts = []) -> + {ok, Socket} = ranch:handshake(Ref), + lager:debug("[sdlan_channel] get a new connection: ~p", [Socket]), + Transport:setopts(Socket, [binary, {active, true}, {packet, 4}]), + % erlang:start_timer(?PING_TICKER, self(), ping_ticker), + gen_server:enter_loop(?MODULE, [], #state{transport = Transport, socket = Socket}). handle_call(_Request, _From, State) -> {reply, ok, State}. %% 发送消息, 基于pub/sub机制 handle_cast({pub, Topic, Content}, State = #state{transport = Transport, socket = Socket}) -> - PubBin = message_pb:encode_msg(#pub{topic = Topic, content = Content}), - Transport:send(Socket, <>), + EncPub = message_codec:encode(?MESSAGE_PUB, #pub{topic = Topic, content = Content}), + Transport:send(Socket, <>), {noreply, State}; %% 发送Command消息 handle_cast({command, CommandType, Command}, State = #state{transport = Transport, socket = Socket}) -> - Transport:send(Socket, <>), + EncCommand = message_codec:encode(?MESSAGE_COMMAND, #command{command_type = CommandType, command = Command}), + Transport:send(Socket, <>), {noreply, State}; %% 推送消息 -handle_cast({async_call, ReceiverPid, Ref, CallType, CallBin}, State = #state{transport = Transport, socket = Socket, packet_id = PacketId, inflight = Inflight}) -> - Transport:send(Socket, <>), +handle_cast({jsonrpc_call, ReceiverPid, Ref, CallBin}, State = #state{transport = Transport, socket = Socket, packet_id = PacketId, inflight = Inflight}) -> + Transport:send(Socket, <>), {noreply, State#state{packet_id = PacketId + 1, inflight = maps:put(PacketId, {ReceiverPid, Ref}, Inflight)}}. %% auth验证 -handle_info({tcp, Socket, <>}, State = #state{transport = Transport, socket = Socket}) -> - #auth_request{ uuid = UUID, username = Username, token = Token, salt = Salt, timestamp = Timestamp } = message_pb:decode_msg(AuthRequestBin, auth_request), +handle_info({tcp, Socket, <>}, State = #state{transport = Transport, socket = Socket}) -> + {ok, #auth_request{uuid = UUID, username = Username, token = Token, salt = Salt, timestamp = Timestamp}} = message_codec:decode(RequestBin), lager:debug("[ws_channel] auth uuid: ~p", [UUID]), case iot_auth:check(Username, Token, UUID, Salt, Timestamp) of true -> - case host_bo:get_host_by_uuid(UUID) of + case iot_api:get_host_by_uuid(UUID) of undefined -> lager:warning("[ws_channel] uuid: ~p, user: ~p, host not found", [UUID, Username]), {stop, State}; @@ -111,20 +107,20 @@ handle_info({tcp, Socket, < %% 建立到host的monitor erlang:monitor(process, HostPid), - AuthReplyBin = message_pb:encode_msg(#auth_reply{code = 0, message = <<"ok">>}), + AuthReplyBin = message_codec:encode(?MESSAGE_AUTH_REPLY, #auth_reply{code = 0, payload = <<"ok">>}), Transport:send(Socket, <>), {noreply, State#state{uuid = UUID, host_pid = HostPid}}; {denied, Reason} when is_binary(Reason) -> erlang:monitor(process, HostPid), - AuthReplyBin = message_pb:encode_msg(#auth_reply{code = 1, message = Reason}), + AuthReplyBin = message_codec:encode(?MESSAGE_AUTH_REPLY, #auth_reply{code = 1, payload = Reason}), Transport:send(Socket, <>), lager:debug("[ws_channel] uuid: ~p, attach channel get error: ~p, stop channel", [UUID, Reason]), {noreply, State#state{uuid = UUID, host_pid = HostPid}}; {error, Reason} when is_binary(Reason) -> - AuthReplyBin = message_pb:encode_msg(#auth_reply{code = 2, message = Reason}), + AuthReplyBin = message_codec:encode(?MESSAGE_AUTH_REPLY, #auth_reply{code = 2, payload = Reason}), Transport:send(Socket, <>), lager:debug("[ws_channel] uuid: ~p, attach channel get error: ~p, stop channel", [UUID, Reason]), @@ -136,59 +132,42 @@ handle_info({tcp, Socket, <>}, State = #state{transport = Transport, socket = Socket}) -> - lager:debug("[ws_channel] service_config request service_id: ~p", [ServiceId]), - case micro_service_bo:get_service_config(ServiceId) of - error -> - Transport:send(Socket, <>); - {ok, ConfigJson} when is_binary(ConfigJson) -> - Transport:send(Socket, <>) +handle_info({tcp, Socket, <>}, State = #state{socket = Socket, host_pid = HostPid}) when is_pid(HostPid) -> + {ok, CastMessage} = message_codec:decode(CastBin), + case CastMessage of + #data{} = Data -> + iot_host:handle(HostPid, {data, Data}); + #event{} = Event -> + iot_host:handle(HostPid, {event, Event}); + #task_event_stream{task_id = TaskId, type = <<"close">>, stream = Reason} -> + iot_event_stream_observer:stream_close(TaskId, Reason); + #task_event_stream{task_id = TaskId, type = Type, stream = Stream} -> + lager:debug("[tcp_channel] get task_id: ~p, type: ~ts, stream: ~ts", [TaskId, Type, Stream]), + iot_event_stream_observer:stream_data(TaskId, Type, Stream) end, {noreply, State}; -handle_info({tcp, Socket, <>}, State = #state{socket = Socket, host_pid = HostPid}) when is_pid(HostPid) -> - Data = message_pb:decode_msg(Data0, data), - iot_host:handle(HostPid, {data, Data}), - {noreply, State}; - -handle_info({tcp, Socket, <>}, State = #state{socket = Socket, host_pid = HostPid}) when is_pid(HostPid) -> - Ping = message_pb:decode_msg(PingData, ping), - iot_host:handle(HostPid, {ping, Ping}), - {noreply, State}; - -handle_info({tcp, Socket, <>}, State = #state{socket = Socket, host_pid = HostPid}) when is_pid(HostPid) -> - ServiceInform = message_pb:decode_msg(InformData, service_inform), - iot_host:handle(HostPid, {inform, ServiceInform}), - {noreply, State}; - -handle_info({tcp, Socket, <>}, State = #state{socket = Socket, host_pid = HostPid}) when is_pid(HostPid) -> - Event = message_pb:decode_msg(EventData, event), - iot_host:handle(HostPid, {event, Event}), - {noreply, State}; +%handle_info({tcp, Socket, <>}, State = #state{socket = Socket, host_pid = HostPid}) when is_pid(HostPid) -> +% Ping = message_pb:decode_msg(PingData, ping), +% iot_host:handle(HostPid, {ping, Ping}), +% {noreply, State}; %% 主机端的消息响应 -handle_info({tcp, Socket, <>}, State = #state{socket = Socket, uuid = UUID, inflight = Inflight}) when PacketId > 0 -> - AsyncCallReply = message_pb:decode_msg(ResponseBin, async_call_reply), - lager:debug("[ws_channel] uuid: ~p, get async_call_reply: ~p, packet_id: ~p", [UUID, AsyncCallReply, PacketId]), +handle_info({tcp, Socket, <>}, State = #state{socket = Socket, uuid = UUID, inflight = Inflight}) when PacketId > 0 -> + {ok, RpcReply} = message_codec:decode(ResponseBin), case maps:take(PacketId, Inflight) of error -> - lager:warning("[ws_channel] get unknown async_call_reply message: ~p, packet_id: ~p", [AsyncCallReply, PacketId]), {noreply, State}; {{ReceiverPid, Ref}, NInflight} -> case is_pid(ReceiverPid) andalso is_process_alive(ReceiverPid) of true -> - ReceiverPid ! {async_call_reply, Ref, AsyncCallReply}; + ReceiverPid ! {jsonrpc_reply, Ref, RpcReply}; false -> - lager:warning("[ws_channel] get async_call_reply message: ~p, packet_id: ~p, but receiver_pid is deaded", [AsyncCallReply, PacketId]) + lager:warning("[ws_channel] get async_call_reply message: ~p, packet_id: ~p, but receiver_pid is deaded", [RpcReply, PacketId]) end, {noreply, State#state{inflight = NInflight}} end; -%% 来自efka的ping包 -handle_info({tcp, Socket, <>}, State = #state{socket = Socket}) -> - {noreply, State}; - handle_info({tcp_error, Sock, Reason}, State = #state{socket = Sock}) -> lager:notice("[sdlan_channel] tcp_error: ~p", [Reason]), {stop, normal, State}; @@ -207,7 +186,7 @@ handle_info({'DOWN', _, process, HostPid, Reason}, State = #state{uuid = UUID, h {stop, State}; handle_info(Info, State) -> - lager:warning("[sdlan_channel] get a unknown message: ~p, channel will closed", [Info]), + lager:warning("[sdlan_channel] get a unknown message: ~p, channel will closed, state: ~p", [Info, State]), {noreply, State}. terminate(Reason, #state{}) -> diff --git a/apps/iot/src/tcp/tcp_server.erl b/apps/iot/src/tcp/tcp_server.erl deleted file mode 100644 index 95ec474..0000000 --- a/apps/iot/src/tcp/tcp_server.erl +++ /dev/null @@ -1,37 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author anlicheng -%%% @copyright (C) 2025, -%%% @doc -%%% -%%% @end -%%% Created : 08. 5月 2025 12:58 -%%%------------------------------------------------------------------- --module(tcp_server). --author("anlicheng"). - -%% API --export([start/0]). - -%% 启动tcp服务 -start() -> - {ok, Props} = application:get_env(iot, tcp_server), - Acceptors = proplists:get_value(acceptors, Props, 50), - MaxConnections = proplists:get_value(max_connections, Props, 10240), - Backlog = proplists:get_value(backlog, Props, 1024), - Port = proplists:get_value(port, Props), - - TransOpts = [ - {tcp_options, [ - binary, - {reuseaddr, true}, - {active, false}, - {packet, 4}, - {nodelay, false}, - {backlog, Backlog} - ]}, - {acceptors, Acceptors}, - {max_connections, MaxConnections} - ], - {ok, _} = esockd:open('iot/tcp_server', Port, TransOpts, {tcp_channel, start_link, []}), - - lager:debug("[iot_app] the tcp server start at: ~p", [Port]). \ No newline at end of file diff --git a/backup/endpoint_mnesia.erl b/backup/endpoint_mnesia.erl deleted file mode 100644 index a1abbdb..0000000 --- a/backup/endpoint_mnesia.erl +++ /dev/null @@ -1,97 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author anlicheng -%%% @copyright (C) 2025, -%%% @doc -%%% -%%% @end -%%% Created : 12. 8月 2025 15:12 -%%%------------------------------------------------------------------- --module(endpoint_mnesia). --author("aresei"). --include("endpoint.hrl"). --include_lib("stdlib/include/qlc.hrl"). - --define(TAB, endpoint). - -%% API --export([create_table/0]). --export([insert/1, delete/1, check_name/1]). --export([get_endpoint/1]). --export([as_map/1]). - -create_table() -> - %% id生成器 - mnesia:create_table(endpoint, [ - {attributes, record_info(fields, endpoint)}, - {record_name, endpoint}, - {disc_copies, [node()]}, - {type, ordered_set} - ]). - --spec check_name(Name :: binary()) -> boolean() | {error, Reason :: any()}. -check_name(Name) when is_binary(Name) -> - Fun = fun() -> - Q = qlc:q([E || E <- mnesia:table(?TAB), E#endpoint.name =:= Name]), - case qlc:e(Q) of - [] -> - false; - [_|_] -> - true - end - end, - case mnesia:transaction(Fun) of - {'atomic', Res} -> - Res; - {'aborted', Reason} -> - {error, Reason} - end. - --spec get_endpoint(Id :: integer()) -> error | {ok, Endpoint :: #endpoint{}}. -get_endpoint(Id) when is_integer(Id) -> - case mnesia:dirty_read(?TAB, Id) of - [] -> - error; - [Endpoint | _] -> - {ok, Endpoint} - end. - --spec insert(Endpoint :: #endpoint{}) -> ok | {error, Reason :: term()}. -insert(Endpoint = #endpoint{}) -> - case mnesia:transaction(fun() -> mnesia:write(?TAB, Endpoint, write) end) of - {'atomic', ok} -> - ok; - {'aborted', Reason} -> - {error, Reason} - end. - --spec delete(Id :: integer()) -> ok | {error, Reason :: any()}. -delete(Id) when is_integer(Id) -> - case mnesia:transaction(fun() -> mnesia:delete(?TAB, Id, write) end) of - {'atomic', ok} -> - ok; - {'aborted', Reason} -> - {error, Reason} - end. - --spec as_map(Endpoint :: #endpoint{}) -> map(). -as_map(#endpoint{id = Id, name = Name, title = Title, config = Config, updated_at = UpdateTs, created_at = CreateTs}) -> - {ConfigKey, ConfigMap} = - case Config of - #http_endpoint{url = Url, pool_size = PoolSize} -> - {<<"http">>, #{<<"url">> => Url, <<"pool_size">> => PoolSize}}; - #mqtt_endpoint{host = Host, port = Port, client_id = ClientId, username = Username, password = Password, topic = Topic, qos = Qos} -> - {<<"mqtt">>, #{<<"host">> => Host, <<"port">> => Port, <<"client_id">> => ClientId, <<"username">> => Username, <<"password">> => Password, <<"topic">> => Topic, <<"qos">> => Qos}}; - #kafka_endpoint{username = Username, password = Password, bootstrap_servers = BootstrapServers, topic = Topic} -> - {<<"kafka">>, #{<<"username">> => Username, <<"password">> => Password, <<"bootstrap_servers">> => BootstrapServers, <<"topic">> => Topic}}; - #mysql_endpoint{host = Host, port = Port, username = Username, password = Password, database = Database, table_name = TableName} -> - {<<"mysql">>, #{<<"host">> => Host, <<"port">> => Port, <<"username">> => Username, <<"password">> => Password, <<"database">> => Database, <<"table_name">> => TableName}} - end, - - Map = #{ - <<"id">> => Id, - <<"name">> => Name, - <<"title">> => Title, - <<"update_ts">> => UpdateTs, - <<"create_ts">> => CreateTs - }, - Map#{ConfigKey => ConfigMap}. \ No newline at end of file diff --git a/backup/endpoint_mysql.erl b/backup/endpoint_mysql.erl deleted file mode 100644 index c9b8a93..0000000 --- a/backup/endpoint_mysql.erl +++ /dev/null @@ -1,214 +0,0 @@ - -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 06. 7月 2023 12:02 -%%%------------------------------------------------------------------- --module(endpoint_mysql). - --include("endpoint.hrl"). --behaviour(gen_server). - -%% API --export([start_link/3]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). - -%% 消息重发间隔 --define(RETRY_INTERVAL, 5000). - --define(DISCONNECTED, disconnected). --define(CONNECTED, connected). - --record(state, { - endpoint :: #endpoint{}, - buffer :: endpoint_buffer:buffer(), - pool_pid :: undefined | pid(), - - status = ?DISCONNECTED -}). - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc Creates a gen_statem process which calls Module:init/1 to -%% initialize. To ensure a synchronized start-up procedure, this -%% function does not return until Module:init/1 has returned. -start_link(LocalName, AliasName, Endpoint = #endpoint{}) when is_atom(LocalName), is_atom(AliasName) -> - gen_statem:start_link({local, LocalName}, ?MODULE, [AliasName, Endpoint], []). - -%%%=================================================================== -%%% gen_statem callbacks -%%%=================================================================== - -%% @private -%% @doc Whenever a gen_statem is started using gen_statem:start/[3,4] or -%% gen_statem:start_link/[3,4], this function is called by the new -%% process to initialize. -init([AliasName, Endpoint]) -> - iot_name_server:register(AliasName, self()), - erlang:process_flag(trap_exit, true), - %% 创建转发器, 避免阻塞当前进程的创建,因此采用了延时初始化的机制 - erlang:start_timer(0, self(), create_postman), - %% 初始化存储 - Buffer = endpoint_buffer:new(Endpoint, 10), - - {ok, #state{endpoint = Endpoint, buffer = Buffer, status = ?DISCONNECTED}}. - -%% @private -%% @doc Handling call messages --spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()}, - State :: #state{}) -> - {reply, Reply :: term(), NewState :: #state{}} | - {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} | - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} | - {stop, Reason :: term(), NewState :: #state{}}). -handle_call(get_stat, _From, State = #state{buffer = Buffer}) -> - Stat = endpoint_buffer:stat(Buffer), - {reply, {ok, Stat}, State}. - -%% @private -%% @doc Handling cast messages --spec(handle_cast(Request :: term(), State :: #state{}) -> - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), NewState :: #state{}}). -handle_cast({forward, ServiceId, Format, Metric}, State = #state{buffer = Buffer}) -> - NBuffer = endpoint_buffer:append({ServiceId, Format, Metric}, Buffer), - {noreply, State#state{buffer = NBuffer}}; - -handle_cast(cleanup, State = #state{buffer = Buffer}) -> - endpoint_buffer:cleanup(Buffer), - {noreply, State}. - -%% @private -%% @doc Handling all non call/cast messages --spec(handle_info(Info :: timeout() | term(), State :: #state{}) -> - {noreply, NewState :: #state{}} | - {noreply, NewState :: #state{}, timeout() | hibernate} | - {stop, Reason :: term(), NewState :: #state{}}). -handle_info({timeout, _, create_postman}, State = #state{status = ?DISCONNECTED, buffer = Buffer, - endpoint = #endpoint{title = Title, config = #mysql_endpoint{host = Host, port = Port, username = Username, password = Password, database = Database}}}) -> - - lager:debug("[iot_endpoint] endpoint: ~p, create postman", [Title]), - WorkerArgs = [ - {host, binary_to_list(Host)}, - {port, Port}, - {user, binary_to_list(Username)}, - {password, binary_to_list(Password)}, - {keep_alive, true}, - {database, binary_to_list(Database)}, - {queries, [<<"set names utf8">>]} - ], - - %% 启动工作的线程池 - PoolSize = 5, - case poolboy:start_link([{size, PoolSize}, {max_overflow, PoolSize}, {worker_module, mysql}], WorkerArgs) of - {ok, PoolPid} -> - NBuffer = endpoint_buffer:trigger_n(Buffer), - {noreply, State#state{pool_pid = PoolPid, buffer = NBuffer, status = ?CONNECTED}}; - ignore -> - retry_connect(), - {noreply, State}; - {error, Reason} -> - lager:warning("[mqtt_postman] start connect pool, get error: ~p", [Reason]), - retry_connect(), - {noreply, State} - end; - -%% 离线时,忽略数据发送逻辑 -handle_info({next_data, _Id, _Tuple}, State = #state{status = ?DISCONNECTED}) -> - {noreply, State}; -%% 发送数据到mqtt服务器 -handle_info({next_data, Id, {ServiceId, Metric}}, State = #state{status = ?CONNECTED, pool_pid = PoolPid, buffer = Buffer, - endpoint = #endpoint{title = Title, config = #mysql_endpoint{table_name = Table, fields_map = FieldsMap}}}) -> - - case insert_sql(Table, ServiceId, FieldsMap, Metric) of - {ok, InsertSql, Values} -> - case poolboy:transaction(PoolPid, fun(ConnPid) -> mysql:query(ConnPid, InsertSql, Values) end) of - ok -> - NBuffer = endpoint_buffer:ack(Id, Buffer), - {noreply, State#state{buffer = NBuffer}}; - Error -> - lager:warning("[endpoint_mysql] endpoint: ~p, insert mysql get error: ~p", [Title, Error]), - {noreply, State} - end; - error -> - lager:debug("[endpoint_mysql] endpoint: ~p, make sql error", [Title]), - {noreply, State} - end; - -%% postman进程挂掉时,重新建立新的 -handle_info({'EXIT', PoolPid, Reason}, State = #state{endpoint = #endpoint{title = Title}, pool_pid = PoolPid}) -> - lager:warning("[enpoint_mqtt] endpoint: ~p, conn pid exit with reason: ~p", [Title, Reason]), - retry_connect(), - {noreply, disconnected, State#state{pool_pid = undefined, status = ?DISCONNECTED}}; - -handle_info(Info, State = #state{status = Status}) -> - lager:warning("[iot_endpoint] unknown message: ~p, status: ~p", [Info, Status]), - {noreply, State}. - -%% @private -%% @doc This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any -%% necessary cleaning up. When it returns, the gen_server terminates -%% with Reason. The return value is ignored. --spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), - State :: #state{}) -> term()). -terminate(Reason, #state{endpoint = #endpoint{title = Title}, buffer = Buffer}) -> - lager:debug("[iot_endpoint] endpoint: ~p, terminate with reason: ~p", [Title, Reason]), - endpoint_buffer:cleanup(Buffer), - ok. - -%% @private -%% @doc Convert process state when code is changed --spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{}, - Extra :: term()) -> - {ok, NewState :: #state{}} | {error, Reason :: term()}). -code_change(_OldVsn, State = #state{}, _Extra) -> - {ok, State}. - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== - -retry_connect() -> - erlang:start_timer(?RETRY_INTERVAL, self(), create_postman). - --spec insert_sql(Table :: binary(), ServiceId :: binary(), FieldsMap :: map(), Metric :: binary()) -> - error | {ok, Sql :: binary(), Values :: list()}. -insert_sql(Table, ServiceId, FieldsMap, Metric) when is_binary(Table), is_binary(ServiceId), is_binary(Metric) -> - case line_format:parse(Metric) of - error -> - error; - {ok, #{<<"measurement">> := Measurement, <<"tags">> := Tags, <<"fields">> := Fields, <<"timestamp">> := Timestamp}} -> - Map = maps:merge(Tags, Fields), - NMap = Map#{<<"measurement">> => Measurement, <<"timestamp">> => Timestamp}, - TableFields = lists:flatmap(fun({TableField, F}) -> - case maps:find(F, NMap) of - error -> - []; - {ok, Val} -> - [{TableField, Val}] - end - end, maps:to_list(FieldsMap)), - - {Keys, Values} = kvs(TableFields), - FieldSql = iolist_to_binary(lists:join(<<", ">>, Keys)), - Placeholders = lists:duplicate(length(Keys), <<"?">>), - ValuesPlaceholder = iolist_to_binary(lists:join(<<", ">>, Placeholders)), - - {ok, <<"INSERT INTO ", Table/binary, "(", FieldSql/binary, ") VALUES(", ValuesPlaceholder/binary, ")">>, Values} - end. - --spec kvs(Fields :: list()) -> {Keys :: list(), Values :: list()}. -kvs(Fields) when is_list(Fields) -> - {Keys0, Values0} = lists:foldl(fun({K, V}, {Acc0, Acc1}) -> {[K|Acc0], [V|Acc1]} end, {[], []}, Fields), - {lists:reverse(Keys0), lists:reverse(Values0)}. \ No newline at end of file diff --git a/backup/service_config_model.erl b/backup/service_config_model.erl deleted file mode 100644 index f37fa2b..0000000 --- a/backup/service_config_model.erl +++ /dev/null @@ -1,121 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author aresei -%%% @copyright (C) 2023, -%%% @doc -%%% -%%% @end -%%% Created : 04. 7月 2023 12:31 -%%%------------------------------------------------------------------- --module(service_config_model). --author("aresei"). --include("iot_tables.hrl"). --include_lib("stdlib/include/qlc.hrl"). - --define(TAB, service_config). - -%% API --export([create_table/0]). --export([insert/4, update/4, get_config/1, delete/1]). --export([as_map/1]). - -create_table() -> - %% id生成器 - mnesia:create_table(service_config, [ - {attributes, record_info(fields, service_config)}, - {record_name, service_config}, - {disc_copies, [node()]}, - {type, ordered_set} - ]). - --spec insert(ServiceId :: binary(), HostUUID :: binary(), ConfigJson :: binary(), LastEditUser :: integer()) -> ok | {error, Reason :: term()}. -insert(ServiceId, HostUUID, ConfigJson, LastEditUser) when is_binary(ServiceId), is_binary(HostUUID), is_binary(ConfigJson), is_integer(LastEditUser) -> - ServiceConfig = #service_config{ - service_id = ServiceId, - host_uuid = HostUUID, - config_json = ConfigJson, - last_config_json = <<>>, - last_edit_user = LastEditUser, - create_ts = iot_util:current_time(), - update_ts = iot_util:current_time() - }, - case mnesia:transaction(fun() -> mnesia:write(?TAB, ServiceConfig, write) end) of - {'atomic', ok} -> - ok; - {'aborted', Reason} -> - {error, Reason} - end. - --spec update(ServiceId :: binary(), HostUUID :: binary(), ConfigJson :: binary(), LastEditUser :: integer()) -> ok | {error, Reason :: term()}. -update(ServiceId, HostUUID, ConfigJson, LastEditUser) when is_binary(ServiceId), is_binary(HostUUID), is_binary(ConfigJson), is_integer(LastEditUser) -> - Fun = fun() -> - case mnesia:read(?TAB, ServiceId, write) of - [] -> - ServiceConfig = #service_config{ - service_id = ServiceId, - host_uuid = HostUUID, - config_json = ConfigJson, - last_config_json = <<>>, - last_edit_user = LastEditUser, - create_ts = iot_util:current_time(), - update_ts = iot_util:current_time() - }, - mnesia:write(?TAB, ServiceConfig, write); - [ServiceConfig0 = #service_config{config_json = OldConfigJson}] -> - NServiceConfig = ServiceConfig0#service_config{ - config_json = ConfigJson, - last_config_json = OldConfigJson, - last_edit_user = LastEditUser, - update_ts = iot_util:current_time() - }, - mnesia:write(?TAB, NServiceConfig, write) - end - end, - - case mnesia:transaction(Fun) of - {'atomic', ok} -> - ok; - {'aborted', Reason} -> - {error, Reason} - end. - --spec get_config(ServiceId :: any()) -> error | {ok, Config :: #service_config{}}. -get_config(ServiceId) when is_binary(ServiceId) -> - case mnesia:dirty_read(?TAB, ServiceId) of - [] -> - error; - [Config] -> - {ok, Config} - end. - --spec delete(ServiceId :: binary()) -> ok | {error, Reason :: any()}. -delete(ServiceId) when is_binary(ServiceId) -> - Fun = fun() -> - case mnesia:read(?TAB, ServiceId, write) of - [] -> - ok; - [ServiceConfig0 = #service_config{config_json = OldConfigJson}] -> - NServiceConfig = ServiceConfig0#service_config{ - config_json = <<"">>, - last_config_json = OldConfigJson, - update_ts = iot_util:current_time() - }, - mnesia:write(?TAB, NServiceConfig, write) - end - end, - case mnesia:transaction(Fun) of - {'atomic', ok} -> - ok; - {'aborted', Reason} -> - {error, Reason} - end. - --spec as_map(ServiceConfig :: #service_config{}) -> map(). -as_map(#service_config{service_id = ServiceId, config_json = ConfigJson, last_config_json = LastConfigJson, last_edit_user = LastEditUser, update_ts = UpdateTs, create_ts = CreateTs}) -> - #{ - <<"service_id">> => ServiceId, - <<"config_json">> => ConfigJson, - <<"last_config_json">> => LastConfigJson, - <<"last_edit_user">> => LastEditUser, - <<"update_ts">> => UpdateTs, - <<"create_ts">> => CreateTs - }. \ No newline at end of file diff --git a/backup/service_handler.erl b/backup/service_handler.erl deleted file mode 100644 index f37bb55..0000000 --- a/backup/service_handler.erl +++ /dev/null @@ -1,176 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author licheng5 -%%% @copyright (C) 2020, -%%% @doc -%%% -%%% @end -%%% Created : 26. 4月 2020 3:36 下午 -%%%------------------------------------------------------------------- --module(service_handler). --author("licheng5"). --include("iot.hrl"). - -%% API --export([handle_request/4]). - -%% 下发config.json, 微服务接受后,保存服务配置 -handle_request("POST", "/service/push_config", _, - #{<<"uuid">> := UUID, <<"service_id">> := ServiceId, <<"last_edit_user">> := LastEditUser, <<"config_json">> := ConfigJson, <<"timeout">> := Timeout0}) - when is_binary(UUID), is_binary(ServiceId), is_binary(ConfigJson), is_integer(Timeout0) -> - - %% 检查ConfigJson是否是合法的json字符串 - case iot_util:is_json(ConfigJson) of - true -> - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(-1, <<"host not found">>)}; - Pid when is_pid(Pid) -> - Timeout = Timeout0 * 1000, - case iot_host:async_service_config(Pid, ServiceId, ConfigJson, Timeout) of - {ok, Ref} -> - case iot_host:await_reply(Ref, Timeout) of - {ok, Result} -> - %% 更新配置信息到数据库 - case service_config_model:update(ServiceId, UUID, ConfigJson, LastEditUser) of - ok -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - lager:debug("[service_handler] set_config service_id: ~p, get error: ~p", [ServiceId, Reason]), - {ok, 200, iot_util:json_error(-1, <<"set service config failed">>)} - end; - {error, Reason} -> - {ok, 200, iot_util:json_error(-1, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(-1, Reason)} - end - end; - false -> - {ok, 200, iot_util:json_error(-1, <<"config is invalid json">>)} - end; - -%% 获取服务配置信息 -handle_request("GET", "/service/get_config", #{<<"service_id">> := ServiceId}, _) when is_binary(ServiceId) -> - case service_config_model:get_config(ServiceId) of - error -> - {ok, 200, iot_util:json_error(-1, <<"service config not found">>)}; - {ok, Config} -> - {ok, 200, iot_util:json_data(service_config_model:as_map(Config))} - end; - -%% 删除对应的主机信息 -handle_request("POST", "/service/delete_config", _, #{<<"service_id">> := ServiceId}) when is_binary(ServiceId) -> - case service_config_model:delete(ServiceId) of - ok -> - {ok, 200, iot_util:json_data(<<"success">>)}; - {error, Reason} -> - lager:debug("[service_handler] delete config of service_id: ~p, error: ~p", [ServiceId, Reason]), - {ok, 200, iot_util:json_error(-1, <<"delete service config errror">>)} - end; - -%% 部署微服务 -handle_request("POST", "/service/deploy", _, #{<<"uuid">> := UUID, <<"task_id">> := TaskId, <<"service_id">> := ServiceId, <<"tar_url">> := TarUrl}) - when is_binary(UUID), is_integer(TaskId), is_binary(ServiceId), is_binary(TarUrl) -> - - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - case iot_host:deploy_service(Pid, TaskId, ServiceId, TarUrl) of - {ok, Ref} -> - case iot_host:await_reply(Ref, 5000) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -%% 启动服务 -handle_request("POST", "/service/start", _, #{<<"uuid">> := UUID, <<"service_id">> := ServiceId}) when is_binary(UUID), is_binary(ServiceId) -> - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - case iot_host:start_service(Pid, ServiceId) of - {ok, Ref} -> - case iot_host:await_reply(Ref, 5000) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -%% 停止服务 -handle_request("POST", "/service/stop", _, #{<<"uuid">> := UUID, <<"service_id">> := ServiceId}) when is_binary(UUID), is_binary(ServiceId) -> - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - case iot_host:stop_service(Pid, ServiceId) of - {ok, Ref} -> - case iot_host:await_reply(Ref, 5000) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -%% 远程调用微服务, 返回值的格式为json -handle_request("POST", "/service/invoke", _, #{<<"uuid">> := UUID, <<"service_id">> := ServiceId, <<"payload">> := Payload, <<"timeout">> := Timeout0}) - when is_binary(UUID), is_binary(ServiceId), is_binary(Payload), is_integer(Timeout0) -> - - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - Timeout = Timeout0 * 1000, - case iot_host:invoke_service(Pid, ServiceId, Payload, Timeout) of - {ok, Ref} -> - case iot_host:await_reply(Ref, Timeout) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -handle_request("POST", "/service/task_log", _, #{<<"uuid">> := UUID, <<"task_id">> := TaskId}) when is_binary(UUID), is_integer(TaskId) -> - case iot_host:get_pid(UUID) of - undefined -> - {ok, 200, iot_util:json_error(404, <<"host not found">>)}; - Pid when is_pid(Pid) -> - case iot_host:task_log(Pid, TaskId) of - {ok, Ref} -> - case iot_host:await_reply(Ref, 5000) of - {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; - {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} - end; - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(400, Reason)} - end - end; - -handle_request(_, Path, _, _) -> - Path1 = list_to_binary(Path), - {ok, 200, iot_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% helper methods -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ No newline at end of file diff --git a/config/sys-dev.config b/config/sys-dev.config index 6b22730..2d3a5df 100644 --- a/config/sys-dev.config +++ b/config/sys-dev.config @@ -25,7 +25,13 @@ {port, 18080} ]}, - {api_url, "http://39.98.184.67:8800/api/v1/taskLog"}, + {api_url, "http://100.123.0.4/api/v1"}, + %% 支持的协议 + {endpoints, [ + {support_protocols, [ + http + ]} + ]}, %% 目标服务器地址 {emqx_server, [ @@ -41,34 +47,34 @@ %% 权限检验时的预埋token {pre_tokens, [ {<<"test">>, <<"iot2023">>} - ]}, - - {pools, [ - %% mysql连接池配置 - {mysql_iot, - [{size, 10}, {max_overflow, 20}, {worker_module, mysql}], - [ - {host, "47.111.101.3"}, - {port, 3306}, - {user, "root"}, - {connect_mode, synchronous}, - {keep_alive, true}, - {password, "r3a-7Qrh#3Q"}, - {database, "nannong_demo"} - ] - }, - - %% redis连接池 - {redis_pool, - [{size, 10}, {max_overflow, 20}, {worker_module, eredis}], - [ - {host, "127.0.0.1"}, - {port, 6379}, - {database, 1} - ] - } ]} + %{pools, [ + % %% mysql连接池配置 + % {mysql_iot, + % [{size, 10}, {max_overflow, 20}, {worker_module, mysql}], + % [ + % {host, "47.111.101.3"}, + % {port, 3306}, + % {user, "root"}, + % {connect_mode, synchronous}, + % {keep_alive, true}, + % {password, "r3a-7Qrh#3Q"}, + % {database, "nannong_demo"} + % ] + % }, + + % %% redis连接池 + % {redis_pool, + % [{size, 10}, {max_overflow, 20}, {worker_module, eredis}], + % [ + % {host, "127.0.0.1"}, + % {port, 6379}, + % {database, 1} + % ] + % } + %]} + ]}, diff --git a/config/sys-prod.config b/config/sys-prod.config index 15c4e5a..6bef008 100644 --- a/config/sys-prod.config +++ b/config/sys-prod.config @@ -29,21 +29,21 @@ {host, "172.19.0.4"}, {port, 8086}, {token, <<"A-ZRjqMK_7NR45lXXEiR7AEtYCd1ETzq9Z61FTMQLb5O4-1hSf8sCrjdPB84e__xsrItKHL3qjJALgbYN-H_VQ==">>} - ]}, - - {pools, [ - %% redis连接池 - {redis_pool, - [{size, 10}, {max_overflow, 20}, {worker_module, eredis}], - [ - {host, "172.30.6.175"}, - {port, 26379}, - {database, 1} - ] - } - ]} + %{pools, [ + % %% redis连接池 + % {redis_pool, + % [{size, 10}, {max_overflow, 20}, {worker_module, eredis}], + % [ + % {host, "172.30.6.175"}, + % {port, 26379}, + % {database, 1} + % ] + % } + + %]} + ]}, diff --git a/docs/endpoint.md b/docs/endpoint.md index 590f8d4..68116bb 100644 --- a/docs/endpoint.md +++ b/docs/endpoint.md @@ -1,63 +1,69 @@ -## Endpoint管理 +## Endpoint数据结构 -### 获取全部的Endpoint +### 数据库表结构 -```html -method: GET -url: /endpoint/all - -返回数据: -[ - { - "name": "名称", - "title": "中电集团" - "matcher": "匹配的正则表达式", - "protocol": "http|https|websocket|mqtt|kafka", - "config": "参考config格式说明" - } -] +```mysql +CREATE TABLE `endpoint` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名称,路由时基于名称', + `title` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '序列号', + `type` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '类型', + `config_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '配置信息,基于json格式存储', + `status` smallint NOT NULL DEFAULT '-1', + `creator` smallint NOT NULL DEFAULT '0' COMMENT '创建人', + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ``` -### 创建Endpoint +### config_json中的数据配置 -```html -method: POST -url: /endpoint/create -body: (content-type: application/json) - {"name": $name, "matcher": $matcher, "title": $title, "protocol": "http|https|websocket|kafka|mqtt", "config": "参考config格式说明"} +#### http方式: type=http +```json -说明: - name是唯一的,不同的终端名称代表不同的接受端 +{ + "url": "http(s)://www.test.com/api", + "pool_size": 10 +} ``` -### 删除Endpoint -```html -method: POST -url: /endpoint/delete -body: (content-type: application/json) - {"name": $name} +#### mqtt方式, type=mqtt +```json + +{ + "host": "127.0.0.1", + "port": 3361, + "client_id": "ClientIdOfMqtt", + "username": "root", + "password": "Password1234", + "topic": "mqtt_topic", + "qos": 0 +} + ``` -### config格式说明 -```html +#### kafka方式, type=kafka + 其中sasl_config可以不配置 +```json - http|https - {"url": "http(s)://xx.com"} +{ + "bootstrap_servers": ["127.0.0.1:9090", "192.168.1.1:9090"], + "topic": "KafkaTopic", + "sasl_config": { + "username": "root", + "password": "password1234", + "mechanism": "sha_256|sha_512|plain" + } +} +``` - websocket - {"url": "ws://xx.com/ws"} +### 关于name的规则说明 +```text + 边缘端的微服务在数据上传的时候需要指定routing_key, 服务器端收到数据后会根据 routing_key = name 对数据进行路由 - kafka: - {"bootstrap_server": ["localhost:9092"], "topic": "test", "username": "test", "password": "password1234"} - - mysql: - {"host": "localhost", port: 3306, "username": "test", "password": "test1234", "database": "iot", "table_name": "north_data"} - - mqtt: - {"host": "localhost", port: 1883, "username": "test", "password": "test1234", "topic": "CET/NX/${location_code}/upload", "qos": 0|1|2} - - topic中支持预定义变量: ${location_code}; 发送的时候会替换成对应的点位编码 -``` \ No newline at end of file +``` diff --git a/docs/iot_api.md b/docs/iot_api.md new file mode 100644 index 0000000..a1f14bb --- /dev/null +++ b/docs/iot_api.md @@ -0,0 +1,409 @@ +--- + +```markdown +# 📘 IoT API 接口文档 + +> 模块:`iot_api` +> 作者:**anlicheng** +> 创建时间:2023-12-24 +> 数据格式:`application/json` +> 认证方式:内置 `API_TOKEN = "wv6fGyBhl*7@AsD9"` + +--- + +## 🔐 通用请求头 + +| Header | 值 | 说明 | +|--------|----|------| +| Content-Type | application/json | 请求体格式 | +| Accept | application/json | 响应体格式 | + +--- + +## 🧩 主机(Host)相关接口 + +### 1. 获取所有主机列表 + +**接口:** +``` + +GET /get_all_hosts + +```` + +**参数:** +无 + +**返回示例:** +```json +{"result": + [ + "uuid-1", + "uuid-2", + "uuid-3" + ] +} +```` +--- + +### 2. 通过 UUID 获取主机信息 + +**接口:** + +``` +GET /get_host_by_uuid?uuid= +``` + +**参数:** + +| 参数名 | 类型 | 必填 | 说明 | +| ---- | ------ | -- | ------- | +| uuid | string | ✅ | 主机 UUID | + +**返回示例:(包含host的全部字段)** + +```json +{ + "result": { + "id": 1, + "uuid": "uuid-1", + "name": "HostA", + "status": 1, + "authorize_status": 1, + "created_at": "2024-01-01T00:00:00Z" + } +} +``` + +--- + +### 3. 通过主机 ID 获取主机信息 + +**接口:** + +``` +GET /get_host_by_id?host_id= +``` + +**参数:** + +| 参数名 | 类型 | 必填 | 说明 | +| ------- | ------- | -- | ----- | +| host_id | integer | ✅ | 主机 ID | + +**返回示例:(包含host的全部字段)** + +```json +{ + "result": { + "id": 1, + "uuid": "uuid-1", + "name": "HostA", + "authorize_status": 1 + } +} +``` + +--- + +### 4. 修改主机状态 + +**接口:** + +``` +POST /change_host_status +``` + +**请求体:** + +```json +{ + "uuid": "uuid-1", + "new_status": 1 +} +``` + +**返回示例:** + +```json +{ + "result": "ok" +} +``` + +--- + +### 5. 获取主机下的设备列表 + +**接口:** + +``` +GET /get_host_devices?host_id= +``` + +**参数:** + +| 参数名 | 类型 | 必填 | 说明 | +| ------- | ------- | -- | ----- | +| host_id | integer | ✅ | 主机 ID | + +**返回示例:(包含device的全部字段)** + +```json +{ + "result": [ + { "device_uuid": "dev-1", "status": 1 }, + { "device_uuid": "dev-2", "status": 0 } + ] +} +``` + +--- + +## 🔧 设备(Device)相关接口 + +### 6. 获取设备详情 + +**接口:** + +``` +GET /get_device_by_uuid?device_uuid= +``` + +**参数:** + +| 参数名 | 类型 | 必填 | 说明 | +| ----------- | ------ | -- | ------- | +| device_uuid | string | ✅ | 设备 UUID | + +**返回示例:(包含device的全部字段)** + +```json +{ + "result": { + "device_uuid": "dev-1", + "type": "sensor", + "status": 1 + } +} +``` + +--- + +### 7. 修改设备状态 + +**接口:** + +``` +POST /change_device_status +``` + +**请求体:** + +```json +{ + "device_uuid": "dev-1", + "new_status": 1 +} +``` + +**返回示例:** + +```json +{ + "result": "ok" +} +``` + +--- + +## 🌐 Endpoint(数据终端)相关接口 + +### 8. 获取所有 Endpoint + +**接口:** + +``` +GET /get_all_endpoints +``` + +**参数:** 无 + +**返回示例:** + +```json +{ + "result": [ + { + "id": 1, + "matcher": "/device/+", + "title": "MQTT 接入节点", + "type": "mqtt", + "status": 1, + "creator": 1, + "created_at": "2024-01-01T00:00:00Z", + "updated_at": "2024-05-01T12:00:00Z", + "config": { + "host": "mqtt.broker.local", + "port": 1883, + "client_id": "iot-client-1", + "username": "iot_user", + "password": "123456", + "topic": "iot/device/data", + "qos": 1 + } + }, + { + "id": 2, + "matcher": "/device/*", + "title": "HTTP 推送接口", + "type": "http", + "status": 1, + "creator": 2, + "created_at": "2024-02-15T10:00:00Z", + "updated_at": "2024-04-01T09:30:00Z", + "config": { + "url": "https://webhook.example.com/data", + "pool_size": 10 + } + }, + { + "id": 3, + "matcher": "/device/*", + "title": "Kafka 接入(认证)", + "type": "kafka", + "status": 1, + "creator": 3, + "created_at": "2024-03-10T08:00:00Z", + "updated_at": "2024-06-20T09:00:00Z", + "config": { + "bootstrap_servers": [ + "kafka1:9092", + "kafka2:9092" + ], + "topic": "iot_topic", + "sasl_config": { + "username": "user_a", + "password": "p@ssw0rd", + "mechanism": "sha_256" + } + } + }, + { + "id": 4, + "matcher": "/device/*", + "title": "Kafka 接入(无认证)", + "type": "kafka", + "status": 1, + "creator": 3, + "created_at": "2024-03-15T09:30:00Z", + "updated_at": "2024-06-25T10:15:00Z", + "config": { + "bootstrap_servers": [ + "kafka1:9092" + ], + "topic": "iot_noauth_topic" + } + } + ] +} + +``` + +--- + +### 9. 获取指定 Endpoint 信息 + +**接口:** + +``` +GET /get_endpoint?id= +``` + +**参数:** + +| 参数名 | 类型 | 必填 | 说明 | +| --- | ------- | -- | ----------- | +| id | integer | ✅ | Endpoint ID | + +**返回示例:()** + +```json +{ + "result": { + "id": 1, + "matcher": "/device/+", + "title": "MQTT接口", + "type": "mqtt", + "config": { + "url": "https://webhook.example.com/data", + "pool_size": 10 + } + } +} +``` + +## 🧱 Endpoint 配置结构说明 + +根据 `type` 不同,`config_json` 结构如下: + +### MQTT + +```json +{ + "host": "broker.example.com", + "port": 1883, + "client_id": "client-1", + "username": "user", + "password": "pass", + "topic": "iot/topic", + "qos": 1 +} +``` + +### HTTP + +```json +{ + "url": "https://api.example.com", + "pool_size": 5 +} +``` + +### Kafka(带认证) + +```json +{ + "bootstrap_servers": ["kafka1:9092", "kafka2:9092"], + "topic": "iot_topic", + "sasl_config": { + "username": "user", + "password": "pass", + "mechanism": "sha_512" + } +} +``` + +### Kafka(无认证) + +```json +{ + "bootstrap_servers": ["kafka1:9092"], + "topic": "iot_topic" +} +``` + +--- + +## ⚠️ 错误响应格式 + +统一错误返回结构: + +```json +{ + "error": { + "code": 400, + "message": "Invalid parameter" + } +} +``` \ No newline at end of file diff --git a/rebar.config b/rebar.config index c87b4b2..9acc2fa 100644 --- a/rebar.config +++ b/rebar.config @@ -1,15 +1,14 @@ {erl_opts, [debug_info]}. {deps, [ {poolboy, ".*", {git, "https://github.com/devinus/poolboy.git", {tag, "1.5.1"}}}, - {hackney, ".*", {git, "https://github.com/benoitc/hackney.git", {tag, "1.16.0"}}}, + {hackney, ".*", {git, "https://github.com/benoitc/hackney.git", {tag, "1.25.0"}}}, {sync, ".*", {git, "https://github.com/rustyio/sync.git", {branch, "master"}}}, - {cowboy, ".*", {git, "https://github.com/ninenines/cowboy.git", {tag, "2.10.0"}}}, - {esockd, ".*", {git, "https://github.com/emqx/esockd.git", {tag, "v5.7.3"}}}, + {cowboy, ".*", {git, "https://github.com/ninenines/cowboy.git", {tag, "2.14.0"}}}, + {ranch, ".*", {git, "https://github.com/ninenines/ranch.git", {tag, "2.2.0"}}}, {brod, ".*", {git, "https://github.com/kafka4beam/brod.git", {tag, "4.4.5"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "1.1.1"}}}, {mysql, ".*", {git, "https://github.com/mysql-otp/mysql-otp", {tag, "1.8.0"}}}, {eredis, ".*", {git, "https://github.com/wooga/eredis.git", {tag, "v1.2.0"}}}, - {gpb, ".*", {git, "https://github.com/tomas-abrahamsson/gpb.git", {tag, "4.20.0"}}}, {emqtt, ".*", {git, "https://gitea.s5s8.com/anlicheng/emqtt.git", {branch, "main"}}}, {gproc, ".*", {git, "https://github.com/uwiger/gproc.git", {tag, "0.9.1"}}}, {parse_trans, ".*", {git, "https://github.com/uwiger/parse_trans", {tag, "3.0.0"}}}, diff --git a/rebar.lock b/rebar.lock index fecc206..dcc80ad 100644 --- a/rebar.lock +++ b/rebar.lock @@ -3,14 +3,14 @@ {git,"https://github.com/kafka4beam/brod.git", {ref,"877852a175f6051b604ea7986bdb8da04ce19e76"}}, 0}, - {<<"certifi">>,{pkg,<<"certifi">>,<<"2.5.2">>},1}, + {<<"certifi">>,{pkg,<<"certifi">>,<<"2.15.0">>},1}, {<<"cowboy">>, {git,"https://github.com/ninenines/cowboy.git", - {ref,"9e600f6c1df3c440bc196b66ebbc005d70107217"}}, + {ref,"e713a630f384f861fa396048f9c881ca183aeda9"}}, 0}, {<<"cowlib">>, {git,"https://github.com/ninenines/cowlib", - {ref,"cc04201c1d0e1d5603cd1cde037ab729b192634c"}}, + {ref,"aca0ad953417b29bab2c41eeb4c37c98606c848b"}}, 1}, {<<"crc32cer">>,{pkg,<<"crc32cer">>,<<"1.0.3">>},2}, {<<"emqtt">>, @@ -21,25 +21,17 @@ {git,"https://github.com/wooga/eredis.git", {ref,"9ad91f149310a7d002cb966f62b7e2c3330abb04"}}, 0}, - {<<"esockd">>, - {git,"https://github.com/emqx/esockd.git", - {ref,"d9ce4024cc42a65e9a05001997031e743442f955"}}, - 0}, {<<"fs">>,{pkg,<<"fs">>,<<"6.1.1">>},1}, {<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.9">>},1}, - {<<"gpb">>, - {git,"https://github.com/tomas-abrahamsson/gpb.git", - {ref,"edda1006d863a09509673778c455d33d88e6edbc"}}, - 0}, {<<"gproc">>, {git,"https://github.com/uwiger/gproc.git", {ref,"4ca45e0a97722a418a31eb1753f4e3b953f7fb1d"}}, 0}, {<<"hackney">>, {git,"https://github.com/benoitc/hackney.git", - {ref,"f3e9292db22c807e73f57a8422402d6b423ddf5f"}}, + {ref,"8c00789e411d7c09a9808d720232098da1f19d69"}}, 0}, - {<<"idna">>,{pkg,<<"idna">>,<<"6.0.1">>},1}, + {<<"idna">>,{pkg,<<"idna">>,<<"6.1.1">>},1}, {<<"jiffy">>, {git,"https://github.com/davisp/jiffy.git", {ref,"9ea1b35b6e60ba21dfd4adbd18e7916a831fd7d4"}}, @@ -50,7 +42,7 @@ {ref,"459a3b2cdd9eadd29e5a7ce5c43932f5ccd6eb88"}}, 0}, {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},1}, - {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},1}, + {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.4.0">>},1}, {<<"mysql">>, {git,"https://github.com/mysql-otp/mysql-otp", {ref,"caf5ff96c677a8fe0ce6f4082bc036c8fd27dd62"}}, @@ -64,36 +56,36 @@ {ref,"3bb48a893ff5598f7c73731ac17545206d259fac"}}, 0}, {<<"ranch">>, - {git,"https://github.com/ninenines/ranch", - {ref,"a692f44567034dacf5efcaa24a24183788594eb7"}}, - 1}, - {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},1}, + {git,"https://github.com/ninenines/ranch.git", + {ref,"9c8520ab8e9c6f3890ac3251d04fbe0b9514940f"}}, + 0}, + {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.7">>},1}, {<<"sync">>, {git,"https://github.com/rustyio/sync.git", - {ref,"f13e61a79623290219d7c10dff1dd94d91eee963"}}, + {ref,"4e909f69d3d0db21a6d7128b20748819e415c9eb"}}, 0}, - {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.5.0">>},2}]}. + {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},1}]}. [ {pkg_hash,[ - {<<"certifi">>, <<"B7CFEAE9D2ED395695DD8201C57A2D019C0C43ECAF8B8BCB9320B40D6662F340">>}, + {<<"certifi">>, <<"0E6E882FCDAAA0A5A9F2B3DB55B1394DBA07E8D6D9BCAD08318FB604C6839712">>}, {<<"crc32cer">>, <<"AD0E42BED8603F2C72DE2A00F1B5063FFE12D5988615CAD984096900431D1C1A">>}, {<<"fs">>, <<"9D147B944D60CFA48A349F12D06C8EE71128F610C90870BDF9A6773206452ED0">>}, {<<"goldrush">>, <<"F06E5D5F1277DA5C413E84D5A2924174182FB108DABB39D5EC548B27424CD106">>}, - {<<"idna">>, <<"1D038FB2E7668CE41FBF681D2C45902E52B3CB9E9C77B55334353B222C2EE50C">>}, + {<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>}, {<<"kafka_protocol">>, <<"6F53B15CD6F6A12C1D0010DB074B4A15985C71BC7F594BC2D67D9837B3B378A1">>}, {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, - {<<"mimerl">>, <<"67E2D3F571088D5CFD3E550C383094B47159F3EEE8FFA08E64106CDF5E981BE3">>}, - {<<"ssl_verify_fun">>, <<"CF344F5692C82D2CD7554F5EC8FD961548D4FD09E7D22F5B62482E5AEAEBD4B0">>}, - {<<"unicode_util_compat">>, <<"8516502659002CEC19E244EBD90D312183064BE95025A319A6C7E89F4BCCD65B">>}]}, + {<<"mimerl">>, <<"3882A5CA67FBBE7117BA8947F27643557ADEC38FA2307490C4C4207624CB213B">>}, + {<<"ssl_verify_fun">>, <<"354C321CF377240C7B8716899E182CE4890C5938111A1296ADD3EC74CF1715DF">>}, + {<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}]}, {pkg_hash_ext,[ - {<<"certifi">>, <<"3B3B5F36493004AC3455966991EAF6E768CE9884693D9968055AEEEB1E575040">>}, + {<<"certifi">>, <<"B147ED22CE71D72EAFDAD94F055165C1C182F61A2FF49DF28BCC71D1D5B94A60">>}, {<<"crc32cer">>, <<"08FDCD5CE51ACD839A12E98742F0F0EDA19A2A679FC9FBFAF6AAB958310FB70E">>}, {<<"fs">>, <<"EF94E95FFE79916860649FED80AC62B04C322B0BB70F5128144C026B4D171F8B">>}, {<<"goldrush">>, <<"99CB4128CFFCB3227581E5D4D803D5413FA643F4EB96523F77D9E6937D994CEB">>}, - {<<"idna">>, <<"A02C8A1C4FD601215BB0B0324C8A6986749F807CE35F25449EC9E69758708122">>}, + {<<"idna">>, <<"92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA">>}, {<<"kafka_protocol">>, <<"1D5E9597AD3C0776C86DC5E08D3BAAEA7DB805A52E5FD35E3F071AAD7789FC4C">>}, {<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>}, - {<<"mimerl">>, <<"F278585650AA581986264638EBF698F8BB19DF297F66AD91B18910DFC6E19323">>}, - {<<"ssl_verify_fun">>, <<"BDB0D2471F453C88FF3908E7686F86F9BE327D065CC1EC16FA4540197EA04680">>}, - {<<"unicode_util_compat">>, <<"D48D002E15F5CC105A696CF2F1BBB3FC72B4B770A184D8420C8DB20DA2674B38">>}]} + {<<"mimerl">>, <<"13AF15F9F68C65884ECCA3A3891D50A7B57D82152792F3E19D88650AA126B144">>}, + {<<"ssl_verify_fun">>, <<"FE4C190E8F37401D30167C8C405EDA19469F34577987C76DDE613E838BBC67F8">>}, + {<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}]} ].