mg.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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 0
  56. pt->voltage = 1.1f;
  57. pt->current = 2.2f;
  58. pt->freq = 3.3f;
  59. pt->power = 4.4f;
  60. pt->consump = 5.5f;
  61. pt->active = 6.6f;
  62. pt->reactive = 7.7f;
  63. pt->apparent = 8.8f;
  64. #else
  65. if (pt->type >= PDU_AC_I3O3) {
  66. cnt = 3;
  67. }
  68. for (i = 0; i < cnt; i++) {
  69. pt->total[i].voltage = rand_float(1.0f, 100.0f);
  70. pt->total[i].current = rand_float(1.0f, 100.0f);
  71. pt->total[i].freq = rand_float(1.0f, 100.0f);
  72. pt->total[i].power = rand_float(1.0f, 100.0f);
  73. pt->total[i].consump = rand_float(1.0f, 100.0f);
  74. pt->total[i].active = rand_float(1.0f, 100.0f);
  75. pt->total[i].reactive = rand_float(1.0f, 100.0f);
  76. }
  77. #endif
  78. }
  79. static void powerc_rand(power_ch_t* pc, uint8_t addr, uint8_t ch, uint8_t sch)
  80. {
  81. int i, cnt = 1;
  82. pc->info.type = PWR_TYPE;
  83. pc->info.addr = addr;
  84. pc->info.ch = ch;
  85. pc->info.sch = sch;
  86. pc->info.ph_id = 0;
  87. pc->info.start_delay = 0;
  88. pc->info.stop_delay = 0;
  89. thr_set(&pc->thr);
  90. alarm_set(&pc->alarm);
  91. if (pc->info.type >= PDU_AC_I3O3) {
  92. cnt = 3;
  93. }
  94. for (i = 0; i < cnt; i++) {
  95. pc->power[i].voltage = rand_float(100.0f, 400.0f);
  96. pc->power[i].current = rand_float(1.0f, 100.0f);
  97. pc->power[i].freq = 50.0f;
  98. pc->power[i].power = rand_float(1.0f, 100.0f);
  99. pc->power[i].consump = rand_float(1.0f, 100.0f);
  100. pc->power[i].factor = rand_float(0.0f, 1.0f);
  101. pc->power[i].status = 1;
  102. pc->power[i].nwire = 0;
  103. }
  104. pc->time = 0;
  105. }
  106. static void send_powerc(struct mg_connection* c)
  107. {
  108. int i, j, ch = 0;
  109. power_ch_t pc;
  110. #if 1
  111. #define BOARD_CNT 2
  112. #define BOARC_CH_CNT 2
  113. //uint8_t addr[BOARD_CNT] = {2,4,6,7,8};
  114. uint8_t addr[BOARD_CNT] = { 2,4 };
  115. #else
  116. #define BOARD_CNT 1
  117. #define BOARC_CH_CNT 1
  118. uint8_t addr[BOARD_CNT] = { 2 };
  119. #endif
  120. for (i = 0; i < BOARD_CNT; i++) {
  121. for (j = 0; j < BOARC_CH_CNT; j++) {
  122. powerc_rand(&pc, addr[i], ch, j);
  123. ws_send(c, PKT_TYPE_POWER_CH, &pc, sizeof(pc));
  124. ch++;
  125. }
  126. }
  127. }
  128. static void send_powert(struct mg_connection* c)
  129. {
  130. power_total_t pt;
  131. powert_rand(&pt);
  132. ws_send(c, PKT_TYPE_POWER_TOTAL, &pt, sizeof(pt));
  133. }
  134. static void send_alarm(struct mg_connection* c)
  135. {
  136. alarm_data_t a;
  137. a.ch = 0;
  138. a.alarm.v_upper = 1;
  139. a.alarm.v_lower = 0;
  140. a.alarm.c_upper = 0;
  141. a.alarm.p_upper = 0;
  142. a.alarm.w_upper = 0;
  143. a.time = 0;
  144. ws_send(c, PKT_TYPE_ALARM, &a, sizeof(a));
  145. }
  146. static int ws_handle(pkt_hdr_t* hdr, struct mg_connection* c)
  147. {
  148. int r = 0;
  149. if (!c->is_websocket) {
  150. printf("___ not a websocket\n");
  151. return -1;
  152. }
  153. if (hdr->magic != PKT_MAGIC) {
  154. printf("___ magic: 0x%x is wrong!, correct is: 0x%x\n", hdr->magic, PKT_MAGIC);
  155. return -1;
  156. }
  157. printf("_____ ws handle, type:%d, subtype:%d, flag:%d\n", hdr->type, hdr->subtype, hdr->flag);
  158. switch (hdr->type) {
  159. case PKT_TYPE_PARAS:
  160. {
  161. //setup
  162. }
  163. break;
  164. case PKT_TYPE_POWER_CH:
  165. {
  166. printf("_____ send_powerc\n");
  167. send_powerc(c);
  168. }
  169. break;
  170. case PKT_TYPE_POWER_TOTAL:
  171. {
  172. printf("_____ send_powert\n");
  173. send_powert(c);
  174. }
  175. break;
  176. case PKT_TYPE_CH_ALL:
  177. {
  178. }
  179. break;
  180. }
  181. return 0;
  182. }
  183. // This RESTful server implements the following endpoints:
  184. // /websocket - upgrade to Websocket, and implement websocket echo server
  185. // /rest - respond with JSON string {"result": 123}
  186. // any other URI serves static files from s_web_root
  187. static void fn(struct mg_connection *c, int ev, void *ev_data) {
  188. if (ev == MG_EV_WS_OPEN) {
  189. } else if (ev == MG_EV_HTTP_MSG) {
  190. struct mg_http_message *hm = (struct mg_http_message *) ev_data;
  191. if (mg_match(hm->uri, mg_str("/ws"), NULL)) {
  192. // Upgrade to websocket. From now on, a connection is a full-duplex
  193. // Websocket connection, which will receive MG_EV_WS_MSG events.
  194. mg_ws_upgrade(c, hm, NULL);
  195. } else if (mg_match(hm->uri, mg_str("/rest"), NULL)) {
  196. // Serve REST response
  197. mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123);
  198. } else {
  199. // Serve static files
  200. struct mg_http_serve_opts opts = {.root_dir = s_web_root};
  201. mg_http_serve_dir(c, (struct mg_http_message*)ev_data, &opts);
  202. }
  203. } else if (ev == MG_EV_WS_MSG) {
  204. // Got websocket frame. Received data is wm->data. Echo it back!
  205. struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
  206. pkt_hdr_t *hdr= (pkt_hdr_t*)wm->data.buf;
  207. ws_handle(hdr, c);
  208. //mg_ws_send(c, wm->data.buf, wm->data.len, WEBSOCKET_OP_TEXT);
  209. }
  210. }
  211. static void timer_fn(void* arg)
  212. {
  213. static uint32_t cnt = 0;
  214. struct mg_mgr* mgr = (struct mg_mgr*)arg;
  215. struct mg_connection* c;
  216. cnt++;
  217. if (cnt%10==0) {
  218. for (c = mgr->conns; c != NULL; c = c->next) {
  219. send_alarm(c);
  220. }
  221. }
  222. }
  223. int main(void) {
  224. struct mg_mgr mgr; // Event manager
  225. srand((uint32_t)time(NULL));
  226. mg_mgr_init(&mgr); // Initialise event manager
  227. printf("ws server on %s/ws\n", s_listen_on);
  228. mg_timer_add(&mgr, 1000, MG_TIMER_REPEAT, timer_fn, &mgr);
  229. mg_http_listen(&mgr, s_listen_on, fn, NULL); // Create HTTP listener
  230. for (;;) mg_mgr_poll(&mgr, 200); // Infinite event loop
  231. mg_mgr_free(&mgr);
  232. return 0;
  233. }