203 publishNData(true, 0); |
205 publishNData(true, 0); |
204 publishDBirthAll(); |
206 publishDBirthAll(); |
205 return; |
207 return; |
206 } |
208 } |
207 } |
209 } |
|
210 |
|
211 /* |
|
212 * DCMD, commands and configuration changes for a single fermenter. |
|
213 */ |
208 if ((strcmp(message_type, "DCMD") == 0) && message_node && message_alias) { |
214 if ((strcmp(message_type, "DCMD") == 0) && message_node && message_alias) { |
209 syslog(LOG_NOTICE, "%s", (char *)json_object_get_string(metric)); |
215 syslog(LOG_NOTICE, "%s", (char *)json_object_get_string(metric)); |
210 for (unit = Config.units ; unit; unit = unit->next) { |
216 for (unit = Config.units ; unit; unit = unit->next) { |
211 if (strcmp(unit->alias, message_alias) == 0) { |
217 if (strcmp(unit->alias, message_alias) == 0) { |
212 syslog(LOG_NOTICE, "MQTT: DCMD for %s/%s", (char *)message_node, (char *)message_alias); |
218 syslog(LOG_NOTICE, "MQTT: DCMD for %s/%s", (char *)message_node, (char *)message_alias); |
213 if (json_object_object_get_ex(metric, "stage", &val)) { |
219 if (json_object_object_get_ex(metric, "stage", &val)) { |
214 // syslog(LOG_NOTICE, "Change state %s", UNITSTAGE[unit->stage]); |
|
215 for (int i = 0; i < 4; i++) { |
220 for (int i = 0; i < 4; i++) { |
216 if (strcmp((char *)json_object_get_string(val), UNITSTAGE[i]) == 0) { |
221 if (strcmp((char *)json_object_get_string(val), UNITSTAGE[i]) == 0) { |
217 if (unit->stage != i) { |
222 if (unit->stage != i) { |
218 syslog(LOG_NOTICE, "DCMD change fermenter %s: stage to %s", message_alias, UNITSTAGE[i]); |
223 syslog(LOG_NOTICE, "DCMD change fermenter %s: stage to %s", message_alias, UNITSTAGE[i]); |
219 unit->mqtt_flag |= MQTT_FLAG_DATA; |
224 unit->mqtt_flag |= MQTT_FLAG_DATA; |
253 * Set a sane default until it will be overruled by the |
258 * Set a sane default until it will be overruled by the |
254 * main processing loop. |
259 * main processing loop. |
255 */ |
260 */ |
256 unit->prof_target_lo = unit->prof_target_hi = 20.0; |
261 unit->prof_target_lo = unit->prof_target_hi = 20.0; |
257 unit->prof_fridge_mode = 0; |
262 unit->prof_fridge_mode = 0; |
258 if (unit->profile) { |
263 if (unit->profile_uuid) { |
259 unit->mqtt_flag |= MQTT_FLAG_DATA; |
264 unit->mqtt_flag |= MQTT_FLAG_DATA; |
260 } |
265 } |
261 } |
266 } |
262 } |
267 } |
263 break; |
268 break; |
264 } |
269 } |
265 } |
270 } |
266 } |
271 } |
267 printf("start setpoint\n"); |
272 |
268 if (json_object_object_get_ex(metric, "setpoint", &setpoint)) { |
273 if (json_object_object_get_ex(metric, "setpoint", &setpoint)) { |
269 if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER)) { |
274 if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER)) { |
270 /* |
275 /* |
271 * Only set new setpoints if running as FRIDGE or in BEER mode. |
276 * Only set new setpoints if running in FRIDGE or in BEER mode. |
272 */ |
277 */ |
273 if (json_object_object_get_ex(setpoint, "low", &val)) { |
278 if (json_object_object_get_ex(setpoint, "low", &val)) |
274 unit->PID_heat->SetP = json_object_get_double(val); |
279 unit->PID_heat->SetP = json_object_get_double(val); |
275 } |
280 if (json_object_object_get_ex(setpoint, "high", &val)) |
276 if (json_object_object_get_ex(setpoint, "high", &val)) { |
|
277 unit->PID_cool->SetP = json_object_get_double(val); |
281 unit->PID_cool->SetP = json_object_get_double(val); |
278 } |
282 if (unit->mode == UNITMODE_FRIDGE) |
279 if (unit->mode == UNITMODE_FRIDGE) { |
|
280 unit->fridge_set = unit->PID_heat->SetP + ((unit->PID_cool->SetP - unit->PID_heat->SetP) / 2); |
283 unit->fridge_set = unit->PID_heat->SetP + ((unit->PID_cool->SetP - unit->PID_heat->SetP) / 2); |
281 } else { |
284 else |
282 unit->beer_set = unit->PID_heat->SetP + ((unit->PID_cool->SetP - unit->PID_heat->SetP) / 2); |
285 unit->beer_set = unit->PID_heat->SetP + ((unit->PID_cool->SetP - unit->PID_heat->SetP) / 2); |
283 } |
|
284 unit->mqtt_flag |= MQTT_FLAG_DATA; |
286 unit->mqtt_flag |= MQTT_FLAG_DATA; |
285 syslog(LOG_NOTICE, "DCMD change fermenter %s: setpoints %.1f %.1f", message_alias, unit->PID_heat->SetP, unit->PID_cool->SetP); |
287 syslog(LOG_NOTICE, "DCMD change fermenter %s: setpoints %.1f %.1f", message_alias, unit->PID_heat->SetP, unit->PID_cool->SetP); |
286 } |
288 } |
287 } |
289 } |
288 printf("start heater\n"); |
290 |
289 if ((json_object_object_get_ex(metric, "heater", &setpoint)) && (unit->mode == UNITMODE_NONE)) { |
291 if ((json_object_object_get_ex(metric, "heater", &setpoint)) && (unit->mode == UNITMODE_NONE)) { |
290 if (json_object_object_get_ex(setpoint, "state", &val)) { |
292 if (json_object_object_get_ex(setpoint, "state", &val)) { |
291 if (json_object_get_int(val) != unit->heater_state) { |
293 if (json_object_get_int(val) != unit->heater_state) { |
292 unit->heater_state = json_object_get_int(val); |
294 unit->heater_state = json_object_get_int(val); |
293 if (unit->heater_state) // Safety |
295 if (unit->heater_state) // Safety |
306 unit->mqtt_flag |= MQTT_FLAG_DATA; |
309 unit->mqtt_flag |= MQTT_FLAG_DATA; |
307 syslog(LOG_NOTICE, "DCMD change fermenter %s: cooler_state to %d", message_alias, unit->cooler_state); |
310 syslog(LOG_NOTICE, "DCMD change fermenter %s: cooler_state to %d", message_alias, unit->cooler_state); |
308 } |
311 } |
309 } |
312 } |
310 } |
313 } |
|
314 |
311 if ((json_object_object_get_ex(metric, "fan", &setpoint)) && (unit->mode == UNITMODE_NONE)) { |
315 if ((json_object_object_get_ex(metric, "fan", &setpoint)) && (unit->mode == UNITMODE_NONE)) { |
312 if (json_object_object_get_ex(setpoint, "state", &val)) { |
316 if (json_object_object_get_ex(setpoint, "state", &val)) { |
313 if (json_object_get_int(val) != unit->fan_state) { |
317 if (json_object_get_int(val) != unit->fan_state) { |
314 unit->fan_state = json_object_get_int(val); |
318 unit->fan_state = json_object_get_int(val); |
315 unit->mqtt_flag |= MQTT_FLAG_DATA; |
319 unit->mqtt_flag |= MQTT_FLAG_DATA; |
316 syslog(LOG_NOTICE, "DCMD change fermenter %s: fan_state to %d", message_alias, unit->fan_state); |
320 syslog(LOG_NOTICE, "DCMD change fermenter %s: fan_state to %d", message_alias, unit->fan_state); |
317 } |
321 } |
318 } |
322 } |
319 } |
323 } |
|
324 |
320 if ((json_object_object_get_ex(metric, "light", &setpoint)) && (unit->mode == UNITMODE_NONE)) { |
325 if ((json_object_object_get_ex(metric, "light", &setpoint)) && (unit->mode == UNITMODE_NONE)) { |
321 if (json_object_object_get_ex(setpoint, "state", &val)) { |
326 if (json_object_object_get_ex(setpoint, "state", &val)) { |
322 if (json_object_get_int(val) != unit->light_state) { |
327 if (json_object_get_int(val) != unit->light_state) { |
323 unit->light_state = json_object_get_int(val); |
328 unit->light_state = json_object_get_int(val); |
324 unit->mqtt_flag |= MQTT_FLAG_DATA; |
329 unit->mqtt_flag |= MQTT_FLAG_DATA; |
325 syslog(LOG_NOTICE, "DCMD change fermenter %s: light_state to %d", message_alias, unit->light_state); |
330 syslog(LOG_NOTICE, "DCMD change fermenter %s: light_state to %d", message_alias, unit->light_state); |
326 } |
331 } |
327 } |
332 } |
328 } |
333 } |
329 printf("start product\n"); |
334 |
330 if ((json_object_object_get_ex(metric, "product", &setpoint)) && (unit->mode == UNITMODE_OFF)) { |
335 if ((json_object_object_get_ex(metric, "product", &setpoint)) && (unit->mode == UNITMODE_OFF)) { |
331 if (json_object_object_get_ex(setpoint, "code", &val)) { |
336 if (json_object_object_get_ex(setpoint, "code", &val)) { |
332 if (strcmp((char *)json_object_get_string(val), unit->product_code)) { |
337 if (strcmp((char *)json_object_get_string(val), unit->product_code)) { |
333 free(unit->product_code); |
338 free(unit->product_code); |
334 unit->product_code = xstrcpy((char *)json_object_get_string(val)); |
339 unit->product_code = xstrcpy((char *)json_object_get_string(val)); |
343 unit->mqtt_flag |= MQTT_FLAG_DATA; |
348 unit->mqtt_flag |= MQTT_FLAG_DATA; |
344 syslog(LOG_NOTICE, "DCMD change fermenter %s: product_name to `%s'", message_alias, unit->product_name); |
349 syslog(LOG_NOTICE, "DCMD change fermenter %s: product_name to `%s'", message_alias, unit->product_name); |
345 } |
350 } |
346 } |
351 } |
347 } |
352 } |
|
353 |
|
354 if (json_object_object_get_ex(metric, "profile", &profile)) { |
|
355 if (json_object_object_get_ex(profile, "command", &profile1)) { |
|
356 syslog(LOG_NOTICE, "profile command"); |
|
357 |
|
358 } else if (json_object_object_get_ex(profile, "uuid", &profile1)) { |
|
359 // syslog(LOG_NOTICE, "profile new profile"); |
|
360 if ((unit->prof_state == PROFILE_OFF) || (unit->prof_state == PROFILE_DONE) || (unit->prof_state == PROFILE_ABORT)) { |
|
361 if (unit->profile_uuid) |
|
362 free(unit->profile_uuid); |
|
363 if (unit->profile_name) |
|
364 free(unit->profile_name); |
|
365 if (unit->profile_steps) { |
|
366 for (step = unit->profile_steps; step; step = oldstep) { |
|
367 if (step->name) |
|
368 free(step->name); |
|
369 oldstep = step->next; |
|
370 free(step); |
|
371 } |
|
372 } |
|
373 unit->profile_steps = NULL; |
|
374 unit->profile_duration = unit->profile_totalsteps = 0; |
|
375 // syslog(LOG_NOTICE, "profile new profile: old cleared"); |
|
376 |
|
377 unit->profile_uuid = xstrcpy((char *)json_object_get_string(profile1)); |
|
378 if (json_object_object_get_ex(profile, "name", &val)) { |
|
379 unit->profile_name = xstrcpy((char *)json_object_get_string(val)); |
|
380 } |
|
381 if (json_object_object_get_ex(profile, "inittemp", &setpoint)) { |
|
382 if (json_object_object_get_ex(setpoint, "low", &val)) { |
|
383 unit->profile_inittemp_lo = json_object_get_double(val); |
|
384 } |
|
385 if (json_object_object_get_ex(setpoint, "high", &val)) { |
|
386 unit->profile_inittemp_hi = json_object_get_double(val); |
|
387 } |
|
388 } |
|
389 if (json_object_object_get_ex(profile, "fridgemode", &val)) { |
|
390 unit->profile_fridge_mode = json_object_get_int(val); |
|
391 if (unit->profile_fridge_mode) |
|
392 unit->profile_fridge_mode = 100; |
|
393 } |
|
394 if (json_object_object_get_ex(profile, "steps", &steps)) { |
|
395 int arraylen = json_object_array_length(steps); |
|
396 syslog(LOG_NOTICE, "profile new profile: start %d steps", arraylen); |
|
397 for (int i = 0; i < arraylen; i++) { |
|
398 /* |
|
399 * Parse the array of steps |
|
400 */ |
|
401 step1 = json_object_array_get_idx(steps, i); |
|
402 unit->profile_totalsteps++; |
|
403 |
|
404 step = (prof_step *)malloc(sizeof(prof_step)); |
|
405 step->next = NULL; |
|
406 step->name = NULL; |
|
407 step->steptime = step->resttime = step->fridge_mode = 0; |
|
408 step->target_lo = step->target_hi = 20.0; |
|
409 |
|
410 if (json_object_object_get_ex(step1, "name", &val)) { |
|
411 step->name = xstrcpy((char *)json_object_get_string(val)); |
|
412 } |
|
413 if (json_object_object_get_ex(step1, "steptime", &val)) { |
|
414 step->steptime = json_object_get_int(val); |
|
415 unit->profile_duration += step->steptime; |
|
416 } |
|
417 if (json_object_object_get_ex(step1, "resttime", &val)) { |
|
418 step->resttime = json_object_get_int(val); |
|
419 unit->profile_duration += step->resttime; |
|
420 } |
|
421 if (json_object_object_get_ex(step1, "fridgemode", &val)) { |
|
422 step->fridge_mode = json_object_get_int(val); |
|
423 if (step->fridge_mode) |
|
424 step->fridge_mode = 100; |
|
425 } |
|
426 if (json_object_object_get_ex(step1, "target_lo", &val)) { |
|
427 step->target_lo = json_object_get_double(val); |
|
428 } |
|
429 if (json_object_object_get_ex(step1, "target_hi", &val)) { |
|
430 step->target_hi = json_object_get_double(val); |
|
431 } |
|
432 |
|
433 syslog(LOG_NOTICE, "profile new profile: add step %d", unit->profile_totalsteps); |
|
434 if (unit->profile_steps == NULL) { |
|
435 unit->profile_steps = step; |
|
436 } else { |
|
437 for (oldstep = unit->profile_steps; oldstep; oldstep = oldstep->next) { |
|
438 if (oldstep->next == NULL) { |
|
439 oldstep->next = step; |
|
440 break; |
|
441 } |
|
442 } |
|
443 } |
|
444 } |
|
445 } |
|
446 unit->mqtt_flag |= MQTT_FLAG_DATA; |
|
447 syslog(LOG_NOTICE, "DCMD change fermenter %s: install profile `%s'", message_alias, unit->profile_name); |
|
448 wrconfig(); |
|
449 } |
|
450 } else { |
|
451 if ((unit->prof_state == PROFILE_OFF) || (unit->prof_state == PROFILE_DONE) || (unit->prof_state == PROFILE_ABORT)) { |
|
452 syslog(LOG_NOTICE, "DCMD change fermenter %s: delete profile `%s'", message_alias, unit->profile_name); |
|
453 if (unit->profile_uuid) |
|
454 free(unit->profile_uuid); |
|
455 if (unit->profile_name) |
|
456 free(unit->profile_name); |
|
457 unit->profile_uuid = unit->profile_name = NULL; |
|
458 if (unit->profile_steps) { |
|
459 for (step = unit->profile_steps; step; step = oldstep) { |
|
460 if (step->name) |
|
461 free(step->name); |
|
462 oldstep = step->next; |
|
463 free(step); |
|
464 } |
|
465 } |
|
466 unit->profile_steps = NULL; |
|
467 unit->profile_inittemp_lo = unit->profile_inittemp_hi = 20.0; |
|
468 unit->prof_percent = unit->profile_fridge_mode = 0; |
|
469 unit->prof_state = PROFILE_OFF; |
|
470 unit->profile_duration = unit->profile_totalsteps = 0; |
|
471 unit->prof_started = unit->prof_paused = unit->prof_primary_done = (time_t)0; |
|
472 unit->prof_peak_abs = unit->prof_peak_rel = 0.0; |
|
473 unit->mqtt_flag |= MQTT_FLAG_DATA; |
|
474 wrconfig(); |
|
475 } |
|
476 } |
|
477 } |
348 } |
478 } |
|
479 |
349 if (unit->mqtt_flag) { |
480 if (unit->mqtt_flag) { |
350 printf("do mqtt flag\n"); |
|
351 if (debug) |
|
352 fprintf(stdout, "flag value %d\n", unit->mqtt_flag); |
|
353 if (unit->mqtt_flag & MQTT_FLAG_BIRTH) { |
481 if (unit->mqtt_flag & MQTT_FLAG_BIRTH) { |
354 publishDBirth(unit); |
482 publishDBirth(unit); |
355 } else { |
483 } else { |
356 publishDData(unit); |
484 publishDData(unit); |
357 } |
485 } |
358 if (unit->mqtt_flag & MQTT_FLAG_DEATH) { |
486 if (unit->mqtt_flag & MQTT_FLAG_DEATH) { |
359 publishDDeath(unit); |
487 publishDDeath(unit); |
360 } |
488 } |
361 unit->mqtt_flag |= MQTT_FLAG_DLOG; // Something to log |
489 unit->mqtt_flag |= MQTT_FLAG_DLOG; // Something to log |
362 } |
490 } |
363 printf("einde unit %s\n", unit->alias); |
|
364 } |
491 } |
365 printf("return\n"); |
|
366 return; |
492 return; |
367 } |
493 } |
368 printf("metric: %s\n", (char *)json_object_get_string(metric)); |
|
369 syslog(LOG_NOTICE, "MQTT: %s payload not understood\n", (char *)message->payload); |
494 syslog(LOG_NOTICE, "MQTT: %s payload not understood\n", (char *)message->payload); |
370 return; |
495 return; |
371 } |
496 } |
372 } else { |
497 } else { |
373 syslog(LOG_NOTICE, "MQTT: got payload with timestamp %d seconds error", timediff); |
498 syslog(LOG_NOTICE, "MQTT: got payload with timestamp %d seconds error", timediff); |
657 payload = xstrcat(payload, buf); |
781 payload = xstrcat(payload, buf); |
658 |
782 |
659 /* |
783 /* |
660 * Loaded profile and state |
784 * Loaded profile and state |
661 */ |
785 */ |
662 if (unit->profile) { |
786 if (unit->profile_uuid) { |
663 for (profile = Config.profiles; profile; profile = profile->next) { |
787 payload = xstrcat(payload, (char *)",\"profile\":{\"uuid\":\""); |
664 if (strcmp(unit->profile, profile->uuid) == 0) { |
788 payload = xstrcat(payload, unit->profile_uuid); |
665 payload = xstrcat(payload, (char *)",\"profile\":{\"uuid\":\""); |
789 payload = xstrcat(payload, (char *)"\",\"name\":\""); |
666 payload = xstrcat(payload, unit->profile); |
790 payload = xstrcat(payload, unit->profile_name); |
667 payload = xstrcat(payload, (char *)"\",\"name\":\""); |
791 payload = xstrcat(payload, (char *)"\",\"state\":\""); |
668 payload = xstrcat(payload, profile->name); |
792 payload = xstrcat(payload, (char *)PROFSTATE[unit->prof_state]); |
669 payload = xstrcat(payload, (char *)"\",\"state\":\""); |
793 payload = xstrcat(payload, (char *)"\",\"percent\":"); |
670 payload = xstrcat(payload, (char *)PROFSTATE[unit->prof_state]); |
794 sprintf(buf, "%d", unit->prof_percent); |
671 payload = xstrcat(payload, (char *)"\",\"percent\":"); |
795 payload = xstrcat(payload, buf); |
672 sprintf(buf, "%d", unit->prof_percent); |
796 payload = xstrcat(payload, (char *)",\"inittemp\":{\"low\":"); |
|
797 sprintf(buf, "%.1f", unit->profile_inittemp_lo); |
|
798 payload = xstrcat(payload, buf); |
|
799 payload = xstrcat(payload, (char *)",\"high\":"); |
|
800 sprintf(buf, "%.1f", unit->profile_inittemp_hi); |
|
801 payload = xstrcat(payload, buf); |
|
802 payload = xstrcat(payload, (char *)"},\"fridgemode\":"); |
|
803 sprintf(buf, "%d", unit->profile_fridge_mode); |
|
804 payload = xstrcat(payload, buf); |
|
805 comma = false; |
|
806 if (unit->profile_steps) { |
|
807 payload = xstrcat(payload, (char *)",\"steps\":["); |
|
808 for (pstep = unit->profile_steps; pstep; pstep = pstep->next) { |
|
809 if (comma) |
|
810 payload = xstrcat(payload, (char *)","); |
|
811 payload = xstrcat(payload, (char *)"{\"resttime\":"); |
|
812 sprintf(buf, "%d", pstep->resttime); |
673 payload = xstrcat(payload, buf); |
813 payload = xstrcat(payload, buf); |
674 payload = xstrcat(payload, (char *)",\"inittemp\":{\"low\":"); |
814 payload = xstrcat(payload, (char *)",\"steptime\":"); |
675 sprintf(buf, "%.1f", profile->inittemp_lo); |
815 sprintf(buf, "%d", pstep->steptime); |
|
816 payload = xstrcat(payload, buf); |
|
817 payload = xstrcat(payload, (char *)",\"target\":{\"low\":"); |
|
818 sprintf(buf, "%.1f", pstep->target_lo); |
676 payload = xstrcat(payload, buf); |
819 payload = xstrcat(payload, buf); |
677 payload = xstrcat(payload, (char *)",\"high\":"); |
820 payload = xstrcat(payload, (char *)",\"high\":"); |
678 sprintf(buf, "%.1f", profile->inittemp_hi); |
821 sprintf(buf, "%.1f", pstep->target_hi); |
679 payload = xstrcat(payload, buf); |
822 payload = xstrcat(payload, buf); |
680 payload = xstrcat(payload, (char *)"},\"fridgemode\":"); |
823 payload = xstrcat(payload, (char *)"},\"fridgemode\":"); |
681 sprintf(buf, "%d", profile->fridge_mode); |
824 sprintf(buf, "%d", pstep->fridge_mode); |
682 payload = xstrcat(payload, buf); |
825 payload = xstrcat(payload, buf); |
683 comma = false; |
826 if (pstep->name) { |
684 if (profile->steps) { |
827 payload = xstrcat(payload, (char *)",\"name\":\""); |
685 payload = xstrcat(payload, (char *)",\"steps\":["); |
828 payload = xstrcat(payload, pstep->name); |
686 for (pstep = profile->steps; pstep; pstep = pstep->next) { |
829 payload = xstrcat(payload, (char *)"\""); |
687 if (comma) |
|
688 payload = xstrcat(payload, (char *)","); |
|
689 payload = xstrcat(payload, (char *)"{\"resttime\":"); |
|
690 sprintf(buf, "%d", pstep->resttime); |
|
691 payload = xstrcat(payload, buf); |
|
692 payload = xstrcat(payload, (char *)",\"steptime\":"); |
|
693 sprintf(buf, "%d", pstep->steptime); |
|
694 payload = xstrcat(payload, buf); |
|
695 payload = xstrcat(payload, (char *)",\"target\":{\"low\":"); |
|
696 sprintf(buf, "%.1f", pstep->target_lo); |
|
697 payload = xstrcat(payload, buf); |
|
698 payload = xstrcat(payload, (char *)",\"high\":"); |
|
699 sprintf(buf, "%.1f", pstep->target_hi); |
|
700 payload = xstrcat(payload, buf); |
|
701 payload = xstrcat(payload, (char *)"},\"fridgemode\":"); |
|
702 sprintf(buf, "%d", pstep->fridge_mode); |
|
703 payload = xstrcat(payload, buf); |
|
704 payload = xstrcat(payload, (char *)"}"); |
|
705 comma = true; |
|
706 } |
|
707 payload = xstrcat(payload, (char *)"]"); |
|
708 } else { |
|
709 payload = xstrcat(payload, (char *)",\"steps\":null"); |
|
710 } |
830 } |
711 payload = xstrcat(payload, (char *)"}"); |
831 payload = xstrcat(payload, (char *)"}"); |
712 break; |
832 comma = true; |
713 } |
833 } |
714 } |
834 payload = xstrcat(payload, (char *)"]"); |
|
835 } else { |
|
836 payload = xstrcat(payload, (char *)",\"steps\":null"); |
|
837 } |
|
838 payload = xstrcat(payload, (char *)"}"); |
715 } else { |
839 } else { |
716 payload = xstrcat(payload, (char *)",\"profile\":null"); |
840 payload = xstrcat(payload, (char *)",\"profile\":null"); |
717 } |
841 } |
718 payload = xstrcat(payload, (char *)"}"); |
842 payload = xstrcat(payload, (char *)"}"); |
719 |
843 |