mg.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // Copyright (c) 2020 Cesanta Software Limited
  2. // All rights reserved
  3. //
  4. // Example Websocket server. See https://mongoose.ws/tutorials/websocket-server/
  5. #include "mongoose.h"
  6. #include "datadef.h"
  7. #define PWR_TYPE PDU_AC_I3O3
  8. static const char *s_listen_on = "ws://localhost";
  9. static const char *s_web_root = ".";
  10. static void send_powerc(struct mg_connection* c);
  11. static int ws_send(struct mg_connection* c, int type, void *data, int len)
  12. {
  13. pkt_hdr_t* h = (pkt_hdr_t*)malloc(sizeof(pkt_hdr_t)+len);
  14. if (!h) {
  15. return -1;
  16. }
  17. h->magic = PKT_MAGIC;
  18. h->type = type;
  19. h->nack = 3;
  20. h->dlen = len;
  21. memcpy(h->data, data, len);
  22. mg_ws_send(c, (const void*)h, sizeof(pkt_hdr_t) + len, WEBSOCKET_OP_BINARY);
  23. free(h);
  24. return 0;
  25. }
  26. static void thrval_set(thr_val_t* tv)
  27. {
  28. tv->en = 0;
  29. tv->val = 100.0f;
  30. tv->act = 0;
  31. memset(tv->para, 0, 14);
  32. }
  33. static void thr_set(thr_t* thr)
  34. {
  35. thrval_set(&thr->v_upper);
  36. thrval_set(&thr->v_lower);
  37. thrval_set(&thr->c_upper);
  38. thrval_set(&thr->p_upper);
  39. thrval_set(&thr->w_upper);
  40. }
  41. static void alarm_set(alarm_t* a)
  42. {
  43. a->v_upper = 1;
  44. a->v_lower = 0;
  45. a->c_upper = 0;
  46. a->p_upper = 0;
  47. a->w_upper = 0;
  48. }
  49. static float rand_float(float min, float max) {
  50. return ((float)rand() / (float)RAND_MAX) * (max - min) + min;
  51. }
  52. static void powert_rand(power_total_t* pt)
  53. {
  54. int i, cnt = 1;
  55. if (pt->type >= PDU_AC_I3O3) {
  56. cnt = 3;
  57. }
  58. for (i = 0; i < cnt; i++) {
  59. pt->total[i].voltage = rand_float(1.0f, 100.0f);
  60. pt->total[i].current = rand_float(1.0f, 100.0f);
  61. pt->total[i].freq = rand_float(1.0f, 100.0f);
  62. pt->total[i].power = rand_float(1.0f, 100.0f);
  63. pt->total[i].consump = rand_float(1.0f, 100.0f);
  64. pt->total[i].active = rand_float(1.0f, 100.0f);
  65. pt->total[i].reactive = rand_float(1.0f, 100.0f);
  66. }
  67. }
  68. static void powerc_rand(power_ch_t* pc, uint8_t addr, uint8_t ch, uint8_t sch)
  69. {
  70. int i, cnt = 1;
  71. pc->info.type = PWR_TYPE;
  72. pc->info.addr = addr;
  73. pc->info.ch = ch;
  74. pc->info.sch = sch;
  75. pc->info.ph_id = 0;
  76. pc->info.start_delay = 0;
  77. pc->info.stop_delay = 0;
  78. thr_set(&pc->thr);
  79. alarm_set(&pc->alarm);
  80. if (pc->info.type >= PDU_AC_I3O3) {
  81. cnt = 3;
  82. }
  83. for (i = 0; i < cnt; i++) {
  84. pc->power[i].voltage = rand_float(100.0f, 400.0f);
  85. pc->power[i].current = rand_float(1.0f, 100.0f);
  86. pc->power[i].freq = 50.0f;
  87. pc->power[i].power = rand_float(1.0f, 100.0f);
  88. pc->power[i].consump = rand_float(1.0f, 100.0f);
  89. pc->power[i].factor = rand_float(0.0f, 1.0f);
  90. pc->power[i].status = 1;
  91. pc->power[i].nwire = 0;
  92. }
  93. pc->time = 0;
  94. }
  95. typedef struct {
  96. uint8_t chs;
  97. power_ch_t pch[CH_MAX];
  98. }powerc_data_t;
  99. static powerc_data_t powerc_data = {.chs=0};
  100. static void send_powerc(struct mg_connection* c)
  101. {
  102. int i, j, ch = 0;
  103. #define BOARD_CNT 2
  104. #define BOARC_CH_CNT 2
  105. //uint8_t addr[BOARD_CNT] = {2,4,6,7,8};
  106. uint8_t addr[BOARD_CNT] = { 2,4 };
  107. powerc_data_t* pc = &powerc_data;
  108. pc->chs = BOARD_CNT * BOARC_CH_CNT;
  109. for (i = 0; i < BOARD_CNT; i++) {
  110. for (j = 0; j < BOARC_CH_CNT; j++) {
  111. powerc_rand(&pc->pch[ch], addr[i], ch, j);
  112. ch++;
  113. }
  114. }
  115. ws_send(c, PKT_TYPE_POWER_CH, pc->pch, sizeof(power_ch_t)*pc->chs);
  116. }
  117. static void send_powert(struct mg_connection* c)
  118. {
  119. power_total_t pt;
  120. powert_rand(&pt);
  121. ws_send(c, PKT_TYPE_POWER_TOTAL, &pt, sizeof(pt));
  122. }
  123. static void send_alarm(struct mg_connection* c)
  124. {
  125. alarm_data_t a;
  126. a.ch = 0;
  127. a.alarm.v_upper = 1;
  128. a.alarm.v_lower = 0;
  129. a.alarm.c_upper = 0;
  130. a.alarm.p_upper = 0;
  131. a.alarm.w_upper = 0;
  132. a.time = 0;
  133. ws_send(c, PKT_TYPE_ALARM, &a, sizeof(a));
  134. }
  135. static int ws_handle(pkt_hdr_t* hdr, struct mg_connection* c)
  136. {
  137. int r = 0;
  138. if (!c->is_websocket) {
  139. printf("___ not a websocket\n");
  140. return -1;
  141. }
  142. if (hdr->magic != PKT_MAGIC) {
  143. printf("___ magic: 0x%x is wrong!, correct is: 0x%x\n", hdr->magic, PKT_MAGIC);
  144. return -1;
  145. }
  146. printf("_____ ws handle, type:%d, subtype:%d, flag:%d\n", hdr->type, hdr->subtype, hdr->flag);
  147. switch (hdr->type) {
  148. case PKT_TYPE_PARAS:
  149. {
  150. //setup
  151. }
  152. break;
  153. case PKT_TYPE_POWER_CH:
  154. {
  155. printf("_____ send_powerc\n");
  156. send_powerc(c);
  157. }
  158. break;
  159. case PKT_TYPE_POWER_TOTAL:
  160. {
  161. printf("_____ send_powert\n");
  162. send_powert(c);
  163. }
  164. break;
  165. case PKT_TYPE_CH_ALL:
  166. {
  167. }
  168. break;
  169. }
  170. return 0;
  171. }
  172. // This RESTful server implements the following endpoints:
  173. // /websocket - upgrade to Websocket, and implement websocket echo server
  174. // /rest - respond with JSON string {"result": 123}
  175. // any other URI serves static files from s_web_root
  176. static void fn(struct mg_connection *c, int ev, void *ev_data) {
  177. if (ev == MG_EV_WS_OPEN) {
  178. } else if (ev == MG_EV_HTTP_MSG) {
  179. struct mg_http_message *hm = (struct mg_http_message *) ev_data;
  180. if (mg_match(hm->uri, mg_str("/ws"), NULL)) {
  181. // Upgrade to websocket. From now on, a connection is a full-duplex
  182. // Websocket connection, which will receive MG_EV_WS_MSG events.
  183. mg_ws_upgrade(c, hm, NULL);
  184. } else if (mg_match(hm->uri, mg_str("/rest"), NULL)) {
  185. // Serve REST response
  186. mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123);
  187. } else {
  188. // Serve static files
  189. struct mg_http_serve_opts opts = {.root_dir = s_web_root};
  190. mg_http_serve_dir(c, (struct mg_http_message*)ev_data, &opts);
  191. }
  192. } else if (ev == MG_EV_WS_MSG) {
  193. // Got websocket frame. Received data is wm->data. Echo it back!
  194. struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
  195. pkt_hdr_t *hdr= (pkt_hdr_t*)wm->data.buf;
  196. ws_handle(hdr, c);
  197. //mg_ws_send(c, wm->data.buf, wm->data.len, WEBSOCKET_OP_TEXT);
  198. }
  199. }
  200. static void timer_fn(void* arg)
  201. {
  202. static uint32_t cnt = 0;
  203. struct mg_mgr* mgr = (struct mg_mgr*)arg;
  204. struct mg_connection* c;
  205. cnt++;
  206. if (cnt%10==0) {
  207. for (c = mgr->conns; c != NULL; c = c->next) {
  208. send_alarm(c);
  209. }
  210. }
  211. }
  212. int main(void) {
  213. struct mg_mgr mgr; // Event manager
  214. srand((uint32_t)time(NULL));
  215. mg_mgr_init(&mgr); // Initialise event manager
  216. printf("ws server on %s/ws\n", s_listen_on);
  217. mg_timer_add(&mgr, 1000, MG_TIMER_REPEAT, timer_fn, &mgr);
  218. mg_http_listen(&mgr, s_listen_on, fn, NULL); // Create HTTP listener
  219. for (;;) mg_mgr_poll(&mgr, 200); // Infinite event loop
  220. mg_mgr_free(&mgr);
  221. return 0;
  222. }