59 |
64 |
60 |
65 |
61 static struct a_message ringbuffer[MAX_MESSAGE_QUEUE]; |
66 static struct a_message ringbuffer[MAX_MESSAGE_QUEUE]; |
62 static int ringbuffer_head; |
67 static int ringbuffer_head; |
63 |
68 |
|
69 |
|
70 |
|
71 void fermenter_ws_receive(char *buf) |
|
72 { |
|
73 struct json_object *val, *val2, *jobj; |
|
74 units_list *unit; |
|
75 bool changed; |
|
76 |
|
77 jobj = json_tokener_parse(buf); |
|
78 json_object_object_get_ex(jobj, "unit", &val); |
|
79 |
|
80 for (unit = Config.units ; unit; unit = unit->next) { |
|
81 if (strcmp((char *)json_object_get_string(val), unit->alias) == 0) { |
|
82 /* |
|
83 * Setpoints |
|
84 * {"type":"fermenter","unit":"unit0","setpoint_low":20.3,"setpoint_high":20.7} |
|
85 */ |
|
86 if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER)) { |
|
87 changed = false; |
|
88 if (json_object_object_get_ex(jobj, "setpoint_low", &val)) { |
|
89 if (unit->PID_heat->SetP != json_object_get_double(val)) { |
|
90 changed = true; |
|
91 syslog(LOG_NOTICE, "ws: unit %s setpoint low from %.1f to %.1f", unit->alias, unit->PID_heat->SetP, json_object_get_double(val)); |
|
92 unit->PID_heat->SetP = json_object_get_double(val); |
|
93 } |
|
94 } |
|
95 if (json_object_object_get_ex(jobj, "setpoint_high", &val)) { |
|
96 if (unit->PID_cool->SetP != json_object_get_double(val)) { |
|
97 changed = true; |
|
98 syslog(LOG_NOTICE, "ws: unit %s setpoint high from %.1f to %.1f", unit->alias, unit->PID_cool->SetP, json_object_get_double(val)); |
|
99 unit->PID_cool->SetP = json_object_get_double(val); |
|
100 } |
|
101 } |
|
102 if (changed) { |
|
103 if (unit->mode == UNITMODE_FRIDGE) { |
|
104 unit->fridge_set_lo = unit->PID_heat->SetP; |
|
105 unit->fridge_set_hi = unit->PID_cool->SetP; |
|
106 } else { |
|
107 unit->beer_set_lo = unit->PID_heat->SetP; |
|
108 unit->beer_set_hi = unit->PID_cool->SetP; |
|
109 } |
|
110 unit->mqtt_flag |= MQTT_FLAG_DATA; |
|
111 break; |
|
112 } |
|
113 } |
|
114 |
|
115 /* |
|
116 * Unit mode |
|
117 * {"type":"fermenter","unit":"unit0","mode":"NONE"} |
|
118 */ |
|
119 if (json_object_object_get_ex(jobj, "mode", &val)) { |
|
120 for (int i = 0; i < 5; i++) { |
|
121 if (strcmp((char *)json_object_get_string(val), UNITMODE[i]) == 0) { |
|
122 if (unit->mode != i) { |
|
123 unit->mqtt_flag |= MQTT_FLAG_DATA; |
|
124 /* Initialize log if the unit is turned on */ |
|
125 if ((unit->mode == UNITMODE_OFF) && (i != UNITMODE_OFF)) { |
|
126 unit->mqtt_flag |= MQTT_FLAG_BIRTH; |
|
127 } |
|
128 if (i == UNITMODE_PROFILE) { |
|
129 /* Do some checks and refuse profile mode cannot be set */ |
|
130 if (unit->profile_uuid == NULL) { |
|
131 syslog(LOG_NOTICE, "ws: unit %s refuse mode profile, not loaded", unit->alias); |
|
132 break; |
|
133 } |
|
134 } |
|
135 syslog(LOG_NOTICE, "ws: unit %s mode to %s", unit->alias, UNITMODE[i]); |
|
136 unit->mode = i; |
|
137 if ((unit->mode != UNITMODE_OFF) && ! unit->event_msg) |
|
138 unit->event_msg = xstrcpy((char *)UNITMODE[i]); |
|
139 /* Allways turn everything off after a mode change */ |
|
140 unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; |
|
141 unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; |
|
142 unit->heater_state = unit->cooler_state = unit->fan_state = unit->light_state = unit->light_timer = 0; |
|
143 unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; |
|
144 device_out(unit->heater_address, unit->heater_state); |
|
145 device_out(unit->cooler_address, unit->cooler_state); |
|
146 device_out(unit->fan_address, unit->fan_state); |
|
147 device_out(unit->light_address, unit->light_state); |
|
148 if (unit->mode == UNITMODE_PROFILE) { |
|
149 /* |
|
150 * Set a sane default until it will be overruled by the |
|
151 * main processing loop. |
|
152 */ |
|
153 unit->prof_target_lo = unit->profile_inittemp_lo; |
|
154 unit->prof_target_hi = unit->profile_inittemp_hi;; |
|
155 unit->prof_fridge_mode = 0; |
|
156 unit->prof_state = PROFILE_OFF; |
|
157 unit->prof_started = unit->prof_paused = unit->prof_primary_done = 0; |
|
158 unit->prof_peak_abs = unit->prof_peak_rel = 0.0; |
|
159 } |
|
160 } |
|
161 break; |
|
162 } |
|
163 } |
|
164 } |
|
165 |
|
166 /* |
|
167 * Unit stage |
|
168 * {"type":"fermenter","unit":"unit0","stage":"SECONDARY"} |
|
169 */ |
|
170 if (json_object_object_get_ex(jobj, "stage", &val)) { |
|
171 for (int i = 0; i < 4; i++) { |
|
172 if (strcmp((char *)json_object_get_string(val), UNITSTAGE[i]) == 0) { |
|
173 if (unit->stage != i) { |
|
174 syslog(LOG_NOTICE, "DCMD change fermenter %s: stage to %s", unit->alias, UNITSTAGE[i]); |
|
175 unit->mqtt_flag |= MQTT_FLAG_DATA; |
|
176 unit->stage = i; |
|
177 if ((unit->mode != UNITMODE_OFF) && ! unit->event_msg) |
|
178 unit->event_msg = xstrcpy((char *)UNITSTAGE[i]); |
|
179 } |
|
180 break; |
|
181 } |
|
182 } |
|
183 } |
|
184 |
|
185 /* |
|
186 * Unit heater and cooler switch |
|
187 * {"type":"fermenter","unit":"unit0","heater_state":100,"cooler_state":0} |
|
188 */ |
|
189 if ((json_object_object_get_ex(jobj, "heater_state", &val)) && |
|
190 (json_object_object_get_ex(jobj, "cooler_state", &val2)) && |
|
191 (unit->mode == UNITMODE_NONE)) { |
|
192 if (json_object_get_int(val) != unit->heater_state) |
|
193 unit->heater_state = json_object_get_int(val); |
|
194 if (json_object_get_int(val2) != unit->cooler_state) |
|
195 unit->cooler_state = json_object_get_int(val2); |
|
196 if (unit->heater_state || unit->cooler_state) |
|
197 unit->heater_state = unit->cooler_state = 0; // Safety |
|
198 unit->mqtt_flag |= MQTT_FLAG_DATA; |
|
199 syslog(LOG_NOTICE, "ws: unit %s heater_state to %d, cooler_state to %d", unit->alias, unit->heater_state, unit->cooler_state); |
|
200 break; |
|
201 } |
|
202 |
|
203 /* |
|
204 * Unit fan switch |
|
205 * {"type":"fermenter","unit":"unit0","fan_state":0} |
|
206 */ |
|
207 if ((json_object_object_get_ex(jobj, "fan_state", &val)) && (unit->mode == UNITMODE_NONE)) { |
|
208 if (json_object_get_int(val) != unit->fan_state) |
|
209 unit->fan_state = json_object_get_int(val); |
|
210 unit->mqtt_flag |= MQTT_FLAG_DATA; |
|
211 syslog(LOG_NOTICE, "ws: unit %s fan_state to %d", unit->alias, unit->fan_state); |
|
212 break; |
|
213 } |
|
214 |
|
215 return; |
|
216 } |
|
217 } |
|
218 syslog(LOG_NOTICE, "fermenter_ws_receive(%s)", buf); |
|
219 } |
64 |
220 |
65 |
221 |
66 static int callback_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) |
222 static int callback_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) |
67 { |
223 { |
68 struct per_session_data__lws_mirror *pss = (struct per_session_data__lws_mirror *)user; |
224 struct per_session_data__lws_mirror *pss = (struct per_session_data__lws_mirror *)user; |
121 * These are send by bmsapp to bmsd. Then bmsd resends these via MQTT. |
277 * These are send by bmsapp to bmsd. Then bmsd resends these via MQTT. |
122 * Do we want to change that? Or use it for the new web pages. |
278 * Do we want to change that? Or use it for the new web pages. |
123 * {"node":"rpi01","group_id":"fermenters","control":"reboot"} |
279 * {"node":"rpi01","group_id":"fermenters","control":"reboot"} |
124 * {"node":"rpi01","group_id":"fermenters","control":"rebirth"} |
280 * {"node":"rpi01","group_id":"fermenters","control":"rebirth"} |
125 */ |
281 */ |
126 // if (strncmp(buf, (char *)"{\"device\":\"fermenters\",", 23) == 0) { |
282 if (strncmp(buf, (char *)"{\"type\":\"fermenter\",", 20) == 0) { |
127 // fermenter_ws_receive(buf); |
283 fermenter_ws_receive(buf); |
128 // } else if (strncmp(buf, (char *)"{\"device\":\"co2meters\",", 22) == 0) { |
284 // } else if (strncmp(buf, (char *)"{\"device\":\"co2meters\",", 22) == 0) { |
129 // co2meter_ws_receive(buf); |
285 // co2meter_ws_receive(buf); |
130 // } else if (strncmp(buf, (char *)"{\"device\":\"ispindels\",", 22) == 0) { |
286 // } else if (strncmp(buf, (char *)"{\"device\":\"ispindels\",", 22) == 0) { |
131 // ispindel_ws_receive(buf); |
287 // ispindel_ws_receive(buf); |
132 // } else if (strncmp(buf, (char *)"{\"node\":\"", 9) == 0) { |
288 // } else if (strncmp(buf, (char *)"{\"node\":\"", 9) == 0) { |
133 // node_ws_receive(buf); |
289 // node_ws_receive(buf); |
134 // } |
290 } |
135 |
291 |
136 break; |
292 break; |
137 |
293 |
138 case LWS_CALLBACK_CLOSED: |
294 case LWS_CALLBACK_CLOSED: |
139 ws_clients--; |
295 ws_clients--; |