提交 5b92158f authored 作者: blu's avatar blu

motion alg, bugfix & more

上级 e67101d9
...@@ -88,25 +88,28 @@ payload: ...@@ -88,25 +88,28 @@ payload:
"mqtt": "admin:password@evcloudsvc.ilabservice.cloud:11883", "mqtt": "admin:password@evcloudsvc.ilabservice.cloud:11883",
"upload": "evcloudsvc.ilabservice.cloud:10009", "upload": "evcloudsvc.ilabservice.cloud:10009",
"features": { "features": {
"push": 1,
"motion": { "motion": {
"enable": 1, "enabled": 1,
"region": { "region": {
"minX": 0.1, "maxX": 1,
"minY": 0.1, "maxY": 1,
"maxX": 0.9, "minX": 0,
"maxY": 0.9 "minY": 0
}, },
"level": 3 "level": 3
}, },
"record":{ "recordLen": 30,
"enable": 1,
"interval": 30,
"duration": 24
},
"ai":{ "ai":{
"enable": 1, "enabled": 1,
"faceThresh": 0.75, "faceThresh": 0.75,
"humanThresh": 0.63 "humanThresh": 0.63,
"region": {
"maxX": 1,
"maxY": 1,
"minX": 0,
"minY": 0
}
} }
} }
} }
...@@ -140,40 +143,43 @@ payload: ...@@ -140,40 +143,43 @@ payload:
```json ```json
{ {
"time":1567669674, "time": ts,
"cmd":"config", "rid": "<request_rid>",
"rid":"001231554A20", "type": "response",
"data":{ "category": "config",
"sn":"001231554A20", "sn": "A000000Z",
"vgw":"192.168.55.104:7123", "code": 0,
"mqtt":"admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883", "msg": "OK",
"upload":"evcloudsvc.ilabservice.cloud:10009", "data": {
"features":{ "vgw": "evcloudsvc.ilabservice.cloud:7123",
"push":"1", "mqtt": "admin:password@evcloudsvc.ilabservice.cloud:11883",
"motion":{ "upload": "evcloudsvc.ilabservice.cloud:10009",
"enabled":0, "features": {
"region":{ "push": 0,
"maxX":0.7, "motion": {
"maxY":0.7, "enabled": 1,
"minX":0.3, "region": {
"minY":0.3 "maxX": 1,
}, "maxY": 1,
"level":4 "minX": 0,
}, "minY": 0
"recordLen":30, },
"ai":{ "level": 3 // 1 - 6
"enabled":1, },
"faceThresh":0.65, "recordLen": 30, // seconds of one slice of local recording
"humanThresh":0.63, "ai":{
"region":{ "enabled": 1,
"maxX":1, "faceThresh": 0.75, // 0 - 1
"maxY":1, "humanThresh": 0.63, // 0 - 1
"minX":0, "region": {
"minY":0 "maxX": 1,
} "maxY": 1,
} "minX": 0,
"minY": 0
}
} }
} }
}
} }
``` ```
...@@ -266,3 +272,35 @@ REQUEST_VIDEOS_T ...@@ -266,3 +272,35 @@ REQUEST_VIDEOS_T
} }
``` ```
### Report: online message
topic: evcamera/v1.0/report
```json
{
"category":"lastwill",
"code":0,
"data":{
"offline":true,
"timestamp_onlie":12121
},
"msg":"new ai capture: pic, idx = 0, toltal = 1",
"rid":"001231554A20",
"sn":"001231554A20",
"time":1589537073532,
"type":"report"
}
```
### Report: offline message (lwm)
topic: evcamera/v1.0/response/<SN>
```json
```
...@@ -209,6 +209,9 @@ smart_LIB_DEPENDS:STATIC= ...@@ -209,6 +209,9 @@ smart_LIB_DEPENDS:STATIC=
//Dependencies for target //Dependencies for target
tcp_client_LIB_DEPENDS:STATIC= tcp_client_LIB_DEPENDS:STATIC=
//Dependencies for target
util_LIB_DEPENDS:STATIC=
######################## ########################
# INTERNAL cache entries # INTERNAL cache entries
......
...@@ -17,7 +17,6 @@ list(APPEND XM_LIBS XmMaQue securec XmSns_50H20AI) ...@@ -17,7 +17,6 @@ list(APPEND XM_LIBS XmMaQue securec XmSns_50H20AI)
include_directories(${CMAKE_SOURCE_DIR} ${PROJECT_SOURCE_DIR} ${COMM_INC_DIR}) include_directories(${CMAKE_SOURCE_DIR} ${PROJECT_SOURCE_DIR} ${COMM_INC_DIR})
link_directories(${COMMON_LIB_DIR} /root/xiongmai/arm-himix100-linux/target/lib/) link_directories(${COMMON_LIB_DIR} /root/xiongmai/arm-himix100-linux/target/lib/)
#add_library(mime STATIC mime.c)
add_library(ntp STATIC ntp.cc) add_library(ntp STATIC ntp.cc)
add_library(tcp_client STATIC raw_tcp.cc) add_library(tcp_client STATIC raw_tcp.cc)
add_library(evutils STATIC evutils.cc) add_library(evutils STATIC evutils.cc)
...@@ -25,7 +24,7 @@ add_library(mqtthelper STATIC ../include/mqtt_helper.cc) ...@@ -25,7 +24,7 @@ add_library(mqtthelper STATIC ../include/mqtt_helper.cc)
add_library(motion STATIC motion.cc) add_library(motion STATIC motion.cc)
add_library(smart STATIC smart.cc) add_library(smart STATIC smart.cc)
add_library(ptz STATIC ptz.cc) add_library(ptz STATIC ptz.cc)
#add_library(util STATIC utils.cpp)
add_executable(evcamera main.cc) add_executable(evcamera main.cc)
target_link_libraries(evcamera PUBLIC ntp paho-mqtt3a mqtthelper tcp_client evutils smart motion ptz zmq ${COMMON_LIBS} ${XM_LIBS}) target_link_libraries(evcamera PUBLIC ntp paho-mqtt3a mqtthelper tcp_client evutils smart motion ptz zmq ${COMMON_LIBS} ${XM_LIBS})
add_executable(test_fsm test_fsm.cc)
\ No newline at end of file
{ {
"time": 1567669674, "time": 1567669674,
"cmd": "config", "cmd": "config",
"rid": "<random_str>", "rid": "001231554A20",
"data": { "data": {
"sn": "A000000Z", "sn": "001231554A20",
"vgw": "192.168.55.104:7123", "vgw": "192.168.55.104:7123",
"mqtt": "admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883", "mqtt": "admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883",
"upload": "evcloudsvc.ilabservice.cloud:10009", "upload": "evcloudsvc.ilabservice.cloud:10009",
......
...@@ -47,9 +47,11 @@ const long long consts::TS_2020 = 1577836800000L; /// ms ...@@ -47,9 +47,11 @@ const long long consts::TS_2020 = 1577836800000L; /// ms
const long long consts::TS_MAX = 9999999999999L; /// ms const long long consts::TS_MAX = 9999999999999L; /// ms
/// topics /// topics
const string consts::sub_topic = "evcamera/v1.0/request/"; const string consts::sub_topic = "/evcamera/v1.0/request/";
const string consts::pub_topic_response = "evcamera/v1.0/response/"; const string consts::pub_topic_response = "/evcamera/v1.0/response/";
const string consts::pub_topic_report = "evcamera/v1.0/report"; const string consts::pub_topic_eventdata = "/evcamera/v1.0/eventdata/";
const string consts::pub_topic_lastwill = "/evcamera/v1.0/lastwill/";
const string consts::pub_topic_report = "/evcamera/v1.0/report";
const string consts::mqtt_url = "tcp://admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883"; const string consts::mqtt_url = "tcp://admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883";
const string consts::vgw_addr = "tcp://evcloudsvc.ilabservice.cloud:7123"; const string consts::vgw_addr = "tcp://evcloudsvc.ilabservice.cloud:7123";
const string consts::upload_addr = "tcp://evcloudsvc.ilabservice.cloud:10009"; const string consts::upload_addr = "tcp://evcloudsvc.ilabservice.cloud:10009";
...@@ -124,6 +126,48 @@ json make_default_sys_extra_config() ...@@ -124,6 +126,48 @@ json make_default_sys_extra_config()
)"_json; )"_json;
} }
json make_lastwill_msg(string sn)
{
json js = R"(
{
"category":"lastwill",
"code":0,
"data":{
},
"msg":"I'M OFFLINE",
"rid":"",
"sn":"001231554A20",
"time":1589537073532,
"type":"report"
}
)"_json;
js["time"] = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
js["sn"] = sn;
return js;
}
json make_online_msg(string sn)
{
json js = R"(
{
"category":"online",
"code":0,
"data":{
},
"msg":"I'M ONLINE",
"rid":"",
"sn":"001231554A20",
"time":1589537073532,
"type":"report"
}
)"_json;
js["time"] = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
js["sn"] = sn;
return js;
}
void get_mac_addr(char *buf, char *intf) void get_mac_addr(char *buf, char *intf)
{ {
char p[] = "/sys/class/net/eth0/address"; char p[] = "/sys/class/net/eth0/address";
...@@ -276,6 +320,7 @@ string save_json(json &data, string path, bool isMerge, fn_mk_default_json mk) ...@@ -276,6 +320,7 @@ string save_json(json &data, string path, bool isMerge, fn_mk_default_json mk)
lock_guard<recursive_mutex> lk(_internal_::mutConfigFiles); lock_guard<recursive_mutex> lk(_internal_::mutConfigFiles);
string rc; string rc;
json js; json js;
json target = data;
if(isMerge) { if(isMerge) {
/// load configuration first /// load configuration first
spdlog::info("save_json merge"); spdlog::info("save_json merge");
...@@ -285,6 +330,7 @@ string save_json(json &data, string path, bool isMerge, fn_mk_default_json mk) ...@@ -285,6 +330,7 @@ string save_json(json &data, string path, bool isMerge, fn_mk_default_json mk)
} }
try { try {
js.merge_or_update(data); js.merge_or_update(data);
target = js;
} }
catch(exception &e) { catch(exception &e) {
rc = fmt::format("failed to merge json: {}, {} + {}", e.what(), js.to_string(), data.to_string()); rc = fmt::format("failed to merge json: {}, {} + {}", e.what(), js.to_string(), data.to_string());
...@@ -295,7 +341,7 @@ string save_json(json &data, string path, bool isMerge, fn_mk_default_json mk) ...@@ -295,7 +341,7 @@ string save_json(json &data, string path, bool isMerge, fn_mk_default_json mk)
ofstream ocfg_(path, std::ios::trunc); ofstream ocfg_(path, std::ios::trunc);
if(ocfg_.is_open()) { if(ocfg_.is_open()) {
ocfg_ << pretty_print(js); ocfg_ << pretty_print(target);
ocfg_.flush(); ocfg_.flush();
ocfg_.close(); ocfg_.close();
} }
...@@ -318,6 +364,10 @@ string load_json(json &config, string path, fn_mk_default_json mk) ...@@ -318,6 +364,10 @@ string load_json(json &config, string path, fn_mk_default_json mk)
spdlog::error("failed loading config {}: {}, force to make default config:\n{}", path, e.what(), config.to_string()); spdlog::error("failed loading config {}: {}, force to make default config:\n{}", path, e.what(), config.to_string());
if(mk != nullptr) { if(mk != nullptr) {
config = mk(); config = mk();
rc = save_json(config, path);
if(!rc.empty()) {
spdlog::error("failed to save_json {}", path);
}
} }
else { else {
rc = "no default make config function provided"; rc = "no default make config function provided";
......
...@@ -64,6 +64,8 @@ typedef struct consts{ ...@@ -64,6 +64,8 @@ typedef struct consts{
/// topics /// topics
static const string sub_topic; static const string sub_topic;
static const string pub_topic_response; static const string pub_topic_response;
static const string pub_topic_eventdata;
static const string pub_topic_lastwill;
static const string pub_topic_report; static const string pub_topic_report;
static const string mqtt_url; static const string mqtt_url;
static const string vgw_addr; static const string vgw_addr;
...@@ -75,6 +77,8 @@ extern string msg_field(const json &msg, const string &field); ...@@ -75,6 +77,8 @@ extern string msg_field(const json &msg, const string &field);
extern bool is_sdcard_avail(char *path = nullptr); extern bool is_sdcard_avail(char *path = nullptr);
extern json make_default_cloud_config(); extern json make_default_cloud_config();
extern json make_default_sys_extra_config(); extern json make_default_sys_extra_config();
extern json make_online_msg(string sn);
extern json make_lastwill_msg(string sn);
extern void get_mac_addr(char *buf, char *intf = nullptr); extern void get_mac_addr(char *buf, char *intf = nullptr);
extern bool get_sdcard_megabytes(uint64_t &total, uint64_t &free, char* path = nullptr); extern bool get_sdcard_megabytes(uint64_t &total, uint64_t &free, char* path = nullptr);
extern int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS=0, int timeoutMs = -1); extern int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS=0, int timeoutMs = -1);
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#define __INTER_TYPES_H__ #define __INTER_TYPES_H__
#include <mqtt_helper.hpp> #include <mqtt_helper.hpp>
#include <inttypes.h>
#include <atomic>
typedef struct ev_region_t { typedef struct ev_region_t {
float minx; float minx;
...@@ -10,29 +12,41 @@ typedef struct ev_region_t { ...@@ -10,29 +12,41 @@ typedef struct ev_region_t {
float maxy; float maxy;
} ev_region_t; } ev_region_t;
typedef struct ev_module_config_t { typedef struct ev_module_config_t {
int stat_current;
ev_region_t region;
bool enabled;
MqttHelper *pClient; MqttHelper *pClient;
union { struct module{
struct { struct record{
int interval; // in seconds int interval; // in seconds
record(){interval = 120;}
} record; } record;
struct { struct ai{
ev_region_t region;
bool enabled;
float face_thresh; //[0,1] float face_thresh; //[0,1]
float human_thresh; float human_thresh;
int image_report_interval; // max in seconds int image_report_interval; // max in seconds
ai(){enabled =true, face_thresh = 0.65, human_thresh = 0.65;}
} ai; } ai;
struct { struct motion{
ev_region_t region;
bool enabled;
int level; // 1 - 6 int level; // 1 - 6
recursive_mutex mut;
//std::atomic<uint64_t> count;
uint64_t count;
motion(){enabled = true, level=3, count = 0;}
} motion; } motion;
struct { struct sys{
int fps; int fps;
int video_quality; int video_quality;
int bitrate_kb; int bitrate_kb;
int bitrate_type; int bitrate_type;
int push; int push;
sys(){fps = 15, video_quality = 5, bitrate_kb = 1024, bitrate_type=1, push=0;}
} sys; } sys;
module(){}
} module; } module;
ev_module_config_t(){
pClient = nullptr;
}
} ev_module_config_t; } ev_module_config_t;
#endif #endif
\ No newline at end of file
差异被折叠。
...@@ -437,17 +437,22 @@ string verify_request(json &js) ...@@ -437,17 +437,22 @@ string verify_request(json &js)
/// low level api for report and response /// low level api for report and response
void _report_response(string topic, string message) void _report_response(string topic, string message)
{ {
auto client = MqttMgr::get_instance(mqtt_url, dev_sn); try {
if(client == nullptr) { auto client = MqttMgr::get_instance(mqtt_url, dev_sn);
spdlog::error("failed to create mqtt instance to {}", mqtt_url); if(client == nullptr) {
return; spdlog::error("failed to create mqtt instance to {}", mqtt_url);
} return;
auto rc = (*client)[topic].pub(message.c_str(), message.size(), 2, false); }
if(rc < 0) { auto rc = (*client)[topic].pub(message.c_str(), message.size(), 2, false);
spdlog::error("failed to pub mqtt message on {}: {}", topic, message); if(rc < 0) {
spdlog::error("failed to pub mqtt message on {}: {}", topic, message);
}
else {
spdlog::info("successfully pub message at {}:{}", topic, message);
}
} }
else { catch(exception &e) {
spdlog::info("successfully pub message at {}:{}", topic, message); spdlog::error("failed to send message: {}, {}, {}:{}", e.what(), message, __FILE__, __LINE__);
} }
} }
...@@ -600,7 +605,7 @@ void handle_mqtt_req(MqttHelper *hlp, const void * const data, int len, string t ...@@ -600,7 +605,7 @@ void handle_mqtt_req(MqttHelper *hlp, const void * const data, int len, string t
} }
catch(exception &e) { catch(exception &e) {
auto str = string("exception: ") + e.what() + string(", ") + msg; auto str = fmt::format("exception {}: {}, {}:{}", e.what(), msg, __FILE__, __LINE__);
spdlog::error(str); spdlog::error(str);
report_response_args(pub_topic, EV_MSG_ERROR_EXCEPTION, str, string(""), string(""), json()); report_response_args(pub_topic, EV_MSG_ERROR_EXCEPTION, str, string(""), string(""), json());
} }
......
...@@ -23,22 +23,19 @@ typedef struct { ...@@ -23,22 +23,19 @@ typedef struct {
XM_S32 bBdEnabled;; XM_S32 bBdEnabled;;
} MdBdMgr_s; } MdBdMgr_s;
std::atomic<uint64_t> gMotionCounter(0);
static int motionCnt = 0;
static XM_S32 cb_motion_detect(XM_VOID *pUserArg, MaQueMdAlarm_s *pstMdAlarm) static XM_S32 cb_motion_detect(XM_VOID *pUserArg, MaQueMdAlarm_s *pstMdAlarm)
{ {
if(motionCnt > 0 ) { ev_module_config_t * pArgs = (ev_module_config_t *)pUserArg;
motionCnt--; gMotionCounter++;
return 0; //spdlog::info("MD eAlarmType: {}, alarmState: {}", pstMdAlarm->eAlarmType, pstMdAlarm->alarmState);
}
motionCnt = 1000;
spdlog::info("Detected, eAlarmType: {}, alarmState: {}", pstMdAlarm->eAlarmType, pstMdAlarm->alarmState);
return 0; return 0;
} }
static XM_S32 cb_blind_detect(XM_VOID *pUserArg, MaQueBdResult_s *pstBdRes) static XM_S32 cb_blind_detect(XM_VOID *pUserArg, MaQueBdResult_s *pstBdRes)
{ {
ev_module_config_t * pArgs = (ev_module_config_t *)pUserArg;
static int prevState = 0; static int prevState = 0;
if(pstBdRes->state != prevState) { if(pstBdRes->state != prevState) {
...@@ -48,14 +45,14 @@ static XM_S32 cb_blind_detect(XM_VOID *pUserArg, MaQueBdResult_s *pstBdRes) ...@@ -48,14 +45,14 @@ static XM_S32 cb_blind_detect(XM_VOID *pUserArg, MaQueBdResult_s *pstBdRes)
else { else {
spdlog::info("The Camera is blind recovered"); spdlog::info("The Camera is blind recovered");
} }
prevState = pstBdRes->state;
} }
prevState = pstBdRes->state;
return 0; return 0;
} }
void start_md_bd(ev_module_config_t *pArgs) void start_md_bd(ev_module_config_t *pArgs)
{ {
if(!pArgs->enabled) { if(!pArgs->module.motion.enabled) {
spdlog::warn("motion detect is disabled"); spdlog::warn("motion detect is disabled");
} }
...@@ -69,24 +66,23 @@ void start_md_bd(ev_module_config_t *pArgs) ...@@ -69,24 +66,23 @@ void start_md_bd(ev_module_config_t *pArgs)
mdParam.stMdParam.y = 48; mdParam.stMdParam.y = 48;
mdParam.stMdParam.w = 352 - 58*2; mdParam.stMdParam.w = 352 - 58*2;
mdParam.stMdParam.h = 288 - 48*2; mdParam.stMdParam.h = 288 - 48*2;
mdParam.stMdParam.eMdAlarmlevel = pArgs->module.motion.level; // [1, 6] mdParam.stMdParam.eMdAlarmlevel = (MaQueMdAlarmLevel_e)pArgs->module.motion.level; // [1, 6]
bdParam.stBdParam.bEnabled = 1; bdParam.stBdParam.bEnabled = 1;
bdParam.stBdParam.eBdAlarmLevel = pArgs->module.motion.level; bdParam.stBdParam.eBdAlarmLevel = (MaQueBdAlarmLevel_e)pArgs->module.motion.level;
if (mdParam.stMdParam.bEnabled) { if (mdParam.stMdParam.bEnabled) {
LibXmMaQue_MD_create(0); LibXmMaQue_MD_create(0);
LibXmMaQue_MD_setParam(0, &mdParam.stMdParam); LibXmMaQue_MD_setParam(0, &mdParam.stMdParam);
LibXmMaQue_MDAlarm_register(0, cb_motion_detect, NULL); LibXmMaQue_MDAlarm_register(0, cb_motion_detect, pArgs);
} }
if (bdParam.stBdParam.bEnabled) { if (bdParam.stBdParam.bEnabled) {
LibXmMaQue_BD_create(0); LibXmMaQue_BD_create(0);
LibXmMaQue_BD_setParam(0, &bdParam.stBdParam); LibXmMaQue_BD_setParam(0, &bdParam.stBdParam);
LibXmMaQue_BD_register(0, cb_blind_detect, NULL); LibXmMaQue_BD_register(0, cb_blind_detect, pArgs);
} }
} }
void stop_md_bd() void stop_md_bd()
{ {
LibXmMaQue_MD_destroy(0); LibXmMaQue_MD_destroy(0);
......
#ifndef __MOTION_DETECT_HPP__
#define __MOTION_DETECT_HPP__
#pragma onece
#include <typeinfo>
#include <sml.hpp>
#include <map>
#include <string>
namespace sml = boost::sml;
namespace md{
/// types
struct none{};
struct motion{};
struct people{};
struct mpboth{};
/// consts
const std::map<const std::string, int> kNumIn2Post = {{"n", 3}, {"m", 6}, {"p", 10}};
const std::map<const std::string, int> kNumPost2None = {{"n", 2}, {"m", 4}, {"p", 8}};
const string kKeyM= "m";
const string kKeyN= "n";
const string kKeyP= "p";
/// helpers
auto event_inspection(auto e, std::map<std::string,int> &m){
if(std::is_same<decltype(e), people>::value){
spdlog::info("type is people: {}", ++m[kKeyP]);
}else if(std::is_same<decltype(e), motion>::value){
spdlog::info("type is motion: {}", ++m[kKeyM]);
}else if(std::is_same<decltype(e), none>::value){
spdlog::info("type is none: {}", ++m[kKeyN]);
}
}
auto make_guard_fn(const std::map<std::string,int> &konst){
return [&konst](auto e){
static std::map<std::string, int>guards = {{"m", 0}, {"p", 0}, {"n", 0}};
event_inspection(e, guards);
if(guards[kKeyM] != 0 && guards[kKeyP] != 0){
guards[kKeyM] = guards[kKeyP] = guards[kKeyN] = 0;
return false;
}else if(guards[kKeyP] >= konst[kKeyP]){
guards[kKeyP]=guards[kKeyN]= 0;
return true;
}else if(guards[kKeyM] >= konst[kKeyM]){
guards[kKeyM]=guards[kKeyN] = 0;
return true;
}else if(guards[kKeyN] >= konst[kKeyN]){
guards[kKeyN] = 0;
return true;
}
return false;
};
}
struct fsm {
auto operator()()const noexcept {
using namespace sml;
const auto guard_in2post = make_guard_fn(kNumIn2Post);
const auto guard_post2none = make_guard_fn(kNumPost2None);
return make_transition_table(
*"init"_s = "none"_s,
"none"_s + event<none>/[]{spdlog::info("none -> none");} = "none"_s,
"none"_s + event<motion>/[]{spdlog::info("none -m-> pre");} = "pre"_s,
"none"_s + event<people>/[]{spdlog::info("none -p-> pre");} = "pre"_s,
"none"_s + event<mpboth>/[]{spdlog::info("none -b-> pre");} = "in"_s,
// pre
"pre"_s + event<none>/[]{spdlog::info("pre -n-> none");} = "none"_s,
"pre"_s + event<motion>/[]{spdlog::info("pre -m-> pre");} = "pre"_s,
"pre"_s + event<people>/[]{spdlog::info("pre -p-> in");} = "in"_s,
"pre"_s + event<mpboth>/[]{spdlog::info("pre -b-> in");} = "in"_s,
// in
"in"_s + event<none> [guard_in2post]/[]{spdlog::info("in -n-> post");} = "post"_s,
"in"_s + event<motion> [guard_in2post]/[]{spdlog::info("in -m-> post");} = "post"_s,
"in"_s + event<people> [guard_in2post]/[]{spdlog::info("in -p-> post");} = "post"_s,
"in"_s + event<mpboth>/[]{spdlog::info("in -b-> in");} = "in"_s,
// post
"post"_s + event<mpboth>/[]{spdlog::info("post -b-> in");} = "in"_s,
"post"_s + event<people> [guard_post2none]/[]{spdlog::info("post -p-> none");} = "none"_s,
"post"_s + event<motion> [guard_post2none]/[]{spdlog::info("post -m-> none");} = "none"_s,
"post"_s + event<none> [guard_post2none]/[]{spdlog::info("post -n-> none");} = "none"_s
);
}
};
}
#endif
\ No newline at end of file
...@@ -10,7 +10,7 @@ using namespace std; ...@@ -10,7 +10,7 @@ using namespace std;
using namespace evutils; using namespace evutils;
using namespace jsoncons; using namespace jsoncons;
mutex gMut; recursive_mutex gMut;
map<string, int> mapDirection = { map<string, int> mapDirection = {
{"left", MOTOR_MOVE_LEFT}, {"left", MOTOR_MOVE_LEFT},
{"right", MOTOR_MOVE_RIGHT}, {"right", MOTOR_MOVE_RIGHT},
...@@ -30,7 +30,7 @@ void ptz_waitfor_idle() ...@@ -30,7 +30,7 @@ void ptz_waitfor_idle()
{ {
XM_U32 action,x,y; XM_U32 action,x,y;
usleep(100*1000); usleep(100*1000);
int cnt = 5 * 10; int cnt = 5 * 20; // wait for max 20s
while (cnt-- > 0) { while (cnt-- > 0) {
spdlog::info("ptz waiting"); spdlog::info("ptz waiting");
if (0 == LibXmMaQue_Motor_getPostion(&action,&x,&y)) { if (0 == LibXmMaQue_Motor_getPostion(&action,&x,&y)) {
...@@ -40,7 +40,8 @@ void ptz_waitfor_idle() ...@@ -40,7 +40,8 @@ void ptz_waitfor_idle()
else { else {
usleep(200*1000); usleep(200*1000);
} }
}else{ }
else {
spdlog::error("ptz failed get position when waiting for idle"); spdlog::error("ptz failed get position when waiting for idle");
break; break;
} }
...@@ -51,19 +52,13 @@ void ptz_waitfor_idle() ...@@ -51,19 +52,13 @@ void ptz_waitfor_idle()
string ptz_service_start() string ptz_service_start()
{ {
static int first_startup = 1;
string rc; string rc;
spdlog::info("start ptz service: calibration/re-locating"); spdlog::info("start ptz service: calibration/re-locating");
if (LibXmMaQue_Motor_create() < 0) { if (LibXmMaQue_Motor_create() < 0) {
rc = "ptz failed start service"; rc = "ptz failed start service";
return rc; return rc;
} }
if(first_startup) { rc = ptz_load();
rc = ptz_reset();
first_startup = 0;
}else{
rc = ptz_load();
}
if(!rc.empty()) { if(!rc.empty()) {
return rc; return rc;
} }
...@@ -124,7 +119,7 @@ string ptz_save() ...@@ -124,7 +119,7 @@ string ptz_save()
js["ptz"]["y"] = pos.current_y_steps; js["ptz"]["y"] = pos.current_y_steps;
spdlog::info("ptz_save current: {}", js.to_string()); spdlog::info("ptz_save current: {}", js.to_string());
rc = save_json(js, extraSysConfigFile, true, evutils::make_default_sys_extra_config); rc = save_json(js, extraSysConfigFile, true, evutils::make_default_sys_extra_config);
if(!rc.empty()){ if(!rc.empty()) {
spdlog::error(rc); spdlog::error(rc);
} }
spdlog::info("ptz_save current end: {}", js.to_string()); spdlog::info("ptz_save current end: {}", js.to_string());
...@@ -140,18 +135,19 @@ string ptz_load() ...@@ -140,18 +135,19 @@ string ptz_load()
return rc; return rc;
} }
rc = save_json(js, extraSysConfigFile, false, evutils::make_default_sys_extra_config); rc = save_json(js, extraSysConfigFile, false, evutils::make_default_sys_extra_config);
if(!rc.empty()){ if(!rc.empty()) {
spdlog::error(rc); spdlog::error(rc);
return rc; return rc;
} }
auto x = js["ptz"]["x"].as<uint32_t>(); auto x = js["ptz"]["x"].as<uint32_t>();
auto y = js["ptz"]["y"].as<uint32_t>(); auto y = js["ptz"]["y"].as<uint32_t>();
if(LibXmMaQue_Motor_setPostion(x,y)) { rc = ptz_relocate(x, y);
rc = fmt::format("failed to set position to {}, {}", x, y); if(!rc.empty()) {
spdlog::error(rc);
return rc;
} }
spdlog::info("ptz load"); spdlog::info("ptz loaded");
ptz_waitfor_idle();
return rc; return rc;
} }
...@@ -159,7 +155,7 @@ string ptz_move(string dire, float degree) ...@@ -159,7 +155,7 @@ string ptz_move(string dire, float degree)
{ {
string rc; string rc;
{ {
lock_guard<mutex> lk(gMut); lock_guard<recursive_mutex> lk(gMut);
if(mapDirection.count(dire) == 0) { if(mapDirection.count(dire) == 0) {
rc = fmt::format("ptz move invalid direction: {}", dire); rc = fmt::format("ptz move invalid direction: {}", dire);
...@@ -174,47 +170,64 @@ string ptz_move(string dire, float degree) ...@@ -174,47 +170,64 @@ string ptz_move(string dire, float degree)
if(dire.find("left") != string::npos || dire.find("right") != string::npos) { if(dire.find("left") != string::npos || dire.find("right") != string::npos) {
curr_pos.current_x_steps = (degree * curr_pos.step_x); curr_pos.current_x_steps = (degree * curr_pos.step_x);
}else{ }
else {
curr_pos.current_x_steps = 0; curr_pos.current_x_steps = 0;
} }
if(dire.find("up")!= string::npos || dire.find("down") != string::npos ) { if(dire.find("up")!= string::npos || dire.find("down") != string::npos ) {
curr_pos.current_y_steps = (degree * curr_pos.step_y); curr_pos.current_y_steps = (degree * curr_pos.step_y);
}else{ }
else {
curr_pos.current_y_steps = 0; curr_pos.current_y_steps = 0;
} }
spdlog::info("ptz executing: {}, {}", dire, degree); spdlog::info("ptz executing: {}, {}", dire, degree);
spdlog::info("motor moving steps: {}, {}", curr_pos.current_x_steps, curr_pos.current_y_steps ); spdlog::info("motor moving steps: {}, {}", curr_pos.current_x_steps, curr_pos.current_y_steps );
if(LibXmMaQue_Motor_move(mapDirection[dire], 6, 6, curr_pos.current_x_steps, curr_pos.current_y_steps) < 0) { if(LibXmMaQue_Motor_move(mapDirection[dire], 6, 6, curr_pos.current_x_steps, curr_pos.current_y_steps) < 0) {
rc = fmt::format("ptz failed to move {} {}: current({},{}), max({},{})", dire, degree, curr_pos.current_x_deg, curr_pos.current_y_deg, 355, 0); rc = fmt::format("ptz failed to move {} {}: current({},{}), max({},{})", dire, degree, curr_pos.current_x_deg, curr_pos.current_y_deg, 355, 0);
if(!rc.empty()) { if(!rc.empty()) {
return rc; return rc;
} }
} }
} }
ptz_waitfor_idle(); ptz_waitfor_idle();
rc = ptz_save(); rc = ptz_save();
return rc; return rc;
} }
string ptz_reset() string ptz_relocate(int x, int y)
{ {
lock_guard<mutex> lk(gMut); lock_guard<recursive_mutex> lk(gMut);
ptz_param_position param; ptz_param_position param;
string rc; string rc;
rc = ptz_get_params(param); rc = ptz_get_params(param);
if(!rc.empty()) { if(!rc.empty()) {
return rc; return rc;
} }
auto targetx = param.max_x/2; // reloacate to center
auto targety = param.max_y/2; uint32_t targetx = 0, targety = 0;
if(x = -1) {
targetx = param.max_x/2;
}
else {
targetx = x;
}
if(y = -1) {
targety = param.max_y/2;
}
else {
targety = y;
}
// move to origin(0,0)
LibXmMaQue_Motor_setZero(); LibXmMaQue_Motor_setZero();
spdlog::info("ptz set zero"); spdlog::info("ptz set zero");
ptz_waitfor_idle(); ptz_waitfor_idle();
spdlog::info("ptz set to zero"); spdlog::info("ptz set to zero");
// move to target (x,y)
auto i = LibXmMaQue_Motor_move(mapDirection["upright"], 6, 6, targetx, targety); auto i = LibXmMaQue_Motor_move(mapDirection["upright"], 6, 6, targetx, targety);
if(i< 0) { if(i< 0) {
rc = fmt::format("ptz failed move to center: {} {}", targetx, targety); rc = fmt::format("ptz failed move to center: {} {}", targetx, targety);
......
...@@ -29,9 +29,10 @@ typedef struct ptz_param_position { ...@@ -29,9 +29,10 @@ typedef struct ptz_param_position {
std::string ptz_service_start(); std::string ptz_service_start();
std::string ptz_service_stop(); std::string ptz_service_stop();
std::string ptz_reset(); std::string ptz_relocate(int x = -1, int y = -1);
std::string ptz_move(std::string dire, float degree); std::string ptz_move(std::string dire, float degree);
std::string ptz_get_params(ptz_param_position & param); std::string ptz_get_params(ptz_param_position & param);
std::string ptz_load(); std::string ptz_load();
std::string ptz_save();
#endif #endif
\ No newline at end of file
差异被折叠。
...@@ -87,6 +87,10 @@ void on_disconn(void* context, MQTTAsync_successData* response) ...@@ -87,6 +87,10 @@ void on_disconn(void* context, MQTTAsync_successData* response)
// self->state = std::promise<MqttHelper::State>(); // self->state = std::promise<MqttHelper::State>();
// } // }
auto js = make_lastwill_msg(self->id);
auto str = js.to_string();
(*self)["hello"].pub(str.c_str(), str.size(), 1, true);
MqttHelper::AsyncResult as; MqttHelper::AsyncResult as;
as.state = MqttHelper::State::Disconnected; as.state = MqttHelper::State::Disconnected;
self->state.set_value(as); self->state.set_value(as);
......
...@@ -106,6 +106,8 @@ protected: ...@@ -106,6 +106,8 @@ protected:
public: public:
string mqtt_url; string mqtt_url;
string id; string id;
string topic_lastwill;
string topic_report;
string addr; string addr;
MQTTAsync client; MQTTAsync client;
enum class State { enum class State {
...@@ -129,7 +131,7 @@ public: ...@@ -129,7 +131,7 @@ public:
/// State state = State::None; // 0: initial ; 1: ready; 2: disconnected; 3: destroyed /// State state = State::None; // 0: initial ; 1: ready; 2: disconnected; 3: destroyed
promise<AsyncResult> state; promise<AsyncResult> state;
MqttHelper(string mqtt_url, string id, int kai = 20, int cs = 1): mqtt_url(mqtt_url), id(id) MqttHelper(string mqtt_url, string id, string topic_lastwill, string topic_report, int kai = 20, int cs = 1): mqtt_url(mqtt_url), id(id), topic_lastwill(topic_lastwill), topic_report(topic_report)
{ {
// make connection, throw excpetions // make connection, throw excpetions
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
...@@ -164,7 +166,15 @@ public: ...@@ -164,7 +166,15 @@ public:
} }
conn_opts.onSuccess = on_connected; conn_opts.onSuccess = on_connected;
conn_opts.onFailure = on_conn_fail; conn_opts.onFailure = on_conn_fail;
MQTTAsync_willOptions lwm = MQTTAsync_willOptions_initializer;
/// template for lastwill message
auto js = make_lastwill_msg(id);
lwm.message = js.to_string().c_str();
lwm.qos = 1;
lwm.retained = 1;
lwm.topicName = topic_lastwill.c_str();
conn_opts.context = this; conn_opts.context = this;
conn_opts.will = &lwm;
spdlog::info("trying to connect to {}", addr); spdlog::info("trying to connect to {}", addr);
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) { if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) {
msg = fmt::format("Failed to start connect: {}", MQTTAsync_strerror(rc)); msg = fmt::format("Failed to start connect: {}", MQTTAsync_strerror(rc));
...@@ -300,21 +310,34 @@ class MqttMgr { ...@@ -300,21 +310,34 @@ class MqttMgr {
static mutex mut; static mutex mut;
public: public:
static MqttHelper* get_instance(string mqtt_url, string devsn){ static MqttHelper* get_instance(string mqtt_url, string devsn, string topic_lastwill="", string topic_report=""){
auto key = mqtt_url + "/" + devsn; auto key = mqtt_url + "/" + devsn;
MqttHelper *ret = nullptr;
lock_guard<mutex> lg(MqttMgr::mut); lock_guard<mutex> lg(MqttMgr::mut);
try{ try{
if(MqttMgr::insts.count(key) == 0){ if(MqttMgr::insts.count(key) == 0){
auto inst = new MqttHelper(mqtt_url, devsn); if(topic_lastwill.empty()){
topic_lastwill = evutils::consts::pub_topic_lastwill + devsn;
}
if(topic_report.empty()){
topic_report = evutils::consts::pub_topic_report;
}
auto inst = new MqttHelper(mqtt_url, devsn, topic_lastwill, topic_report);
auto js = make_online_msg(devsn);
auto msg = js.to_string();
auto rc = (*inst)[topic_report].pub(msg.c_str(), msg.size(), 2, false);
ret = inst;
MqttMgr::insts[key] = inst; MqttMgr::insts[key] = inst;
}else{ }else{
// ret = MqttMgr::insts[key];
} }
}catch(exception &e) { }catch(exception &e) {
spdlog::error("failed to create mqtt adaptor: {}", e.what()); spdlog::error("failed to create mqtt adaptor: {}", e.what());
} }
return MqttMgr::insts[key]; return ret;
} }
static void remove(string mqtt_url, string devsn){ static void remove(string mqtt_url, string devsn){
...@@ -349,7 +372,7 @@ class MqttMgr { ...@@ -349,7 +372,7 @@ class MqttMgr {
auto rc = (*client)[topic].pub(message.c_str(), message.size(), 2, false); auto rc = (*client)[topic].pub(message.c_str(), message.size(), 2, false);
if(message.size() > EV_MAX_PRINTABLE_SIZE){ if(message.size() > EV_MAX_PRINTABLE_SIZE){
string ellipsis = " <...> "; string ellipsis = " <...> ";
message = message.substr(0, EV_MAX_PRINTABLE_SIZE/2 - ellipsis.size()) + ellipsis + message.substr(EV_MAX_PRINTABLE_SIZE/2, EV_MAX_PRINTABLE_SIZE/2); message = message.substr(0, EV_MAX_PRINTABLE_SIZE/2 - ellipsis.size()) + ellipsis + message.substr(message.size() -1 - EV_MAX_PRINTABLE_SIZE/2, EV_MAX_PRINTABLE_SIZE/2);
} }
if(rc < 0) { if(rc < 0) {
spdlog::error("failed to pub mqtt message on {}: {}", topic, message); spdlog::error("failed to pub mqtt message on {}: {}", topic, message);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论