reorganize code and added documentation
This commit is contained in:
@@ -9,17 +9,39 @@
|
||||
|
||||
#include "console.h"
|
||||
|
||||
char *device_config_file = "./flapconfig.json";
|
||||
char *device_config_file;
|
||||
int fd;
|
||||
// command handlers
|
||||
/*
|
||||
* Command parser for wsserver.
|
||||
* Parses incoming json commands and executes corresponding functions.
|
||||
*/
|
||||
|
||||
// dump config/ all devices
|
||||
|
||||
/*
|
||||
* command: dm_dump
|
||||
* description: dump all device details as json to websocket
|
||||
*
|
||||
* request format: { "command": "dm_dump" }
|
||||
* response format: { ... all device details ... }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_dump(json_object *req, json_object *res)
|
||||
{
|
||||
devicemgr_printDetailsAll(res);
|
||||
}
|
||||
|
||||
// describe single device
|
||||
/*
|
||||
* command: dm_describe
|
||||
* description: describe device with id as json to websocket
|
||||
*
|
||||
* request format: { "command": "dm_describe", "id": <device_id> }
|
||||
* response format: { ... device details ... }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_describe(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *id;
|
||||
@@ -34,7 +56,16 @@ void cmd_dm_describe(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
// register new device
|
||||
/*
|
||||
* command: dm_register
|
||||
* description: register new device at address with x,y position
|
||||
*
|
||||
* request format: { "command": "dm_register", "address": <address>, "x": <x>, "y": <y> }
|
||||
* response format: { "id": <new_device_id> }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_register(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jaddress, *jx, *jy;
|
||||
@@ -65,7 +96,16 @@ void cmd_dm_register(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
// refresh all devices
|
||||
/*
|
||||
* command: dm_refresh
|
||||
* description: refresh all devices and update their status
|
||||
*
|
||||
* request format: { "command": "dm_refresh" }
|
||||
* response format: { "devices_online": <number_of_online_devices> }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_refresh(json_object *req, json_object *res)
|
||||
{
|
||||
int devices_online = devicemgr_refresh();
|
||||
@@ -73,7 +113,16 @@ void cmd_dm_refresh(json_object *req, json_object *res)
|
||||
}
|
||||
|
||||
|
||||
// remove device
|
||||
/*
|
||||
* command: dm_remove
|
||||
* description: remove device with id from device manager
|
||||
*
|
||||
* request format: { "command": "dm_remove", "id": <device_id> }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_remove(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jid;
|
||||
@@ -91,14 +140,32 @@ void cmd_dm_remove(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
// save all devices
|
||||
/*
|
||||
* command: dm_save
|
||||
* description: save all devices to config file
|
||||
*
|
||||
* request format: { "command": "dm_save" }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_save(json_object *req, json_object *res)
|
||||
{
|
||||
devicemgr_save(device_config_file);
|
||||
json_object_object_add(res, "ack", json_object_new_boolean(true));
|
||||
}
|
||||
|
||||
// load all devices
|
||||
/*
|
||||
* command: dm_load
|
||||
* description: load all devices from config file
|
||||
*
|
||||
* request format: { "command": "dm_load" }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_load(json_object *req, json_object *res)
|
||||
{
|
||||
devicemgr_load(device_config_file);
|
||||
@@ -106,7 +173,16 @@ void cmd_dm_load(json_object *req, json_object *res)
|
||||
}
|
||||
|
||||
|
||||
// print string on display
|
||||
/*
|
||||
* command: dm_print
|
||||
* description: print text to display at position (x,y)
|
||||
*
|
||||
* request format: { "command": "dm_print", "x": <x>, "y": <y>, "string": <text> }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_print(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jx = json_object_object_get(req, "x");
|
||||
@@ -137,7 +213,16 @@ void cmd_dm_print(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
// set flap on display
|
||||
/*
|
||||
* command: dm_print_single
|
||||
* description: print single flap to display at position (x,y)
|
||||
*
|
||||
* request format: { "command": "dm_print_single", "x": <x>, "y": <y>, "flap": <flap_id> }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_print_single(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jx = json_object_object_get(req, "x");
|
||||
@@ -169,16 +254,33 @@ void cmd_dm_print_single(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
// clear display
|
||||
/*
|
||||
* command: dm_clear
|
||||
* description: clear all displays (set to flap 0)
|
||||
*
|
||||
* request format: { "command": "dm_clear" }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dm_clear(json_object *req, json_object *res)
|
||||
{
|
||||
devicemgr_clearscreen();
|
||||
json_object_object_add(res, "ack", json_object_new_boolean(true));
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ping device
|
||||
/*
|
||||
* command: dr_ping
|
||||
* description: ping device at address
|
||||
*
|
||||
* request format: { "command": "dr_ping", "address": <address> }
|
||||
* response format: { "success": true/false }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dr_ping(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jaddr = json_object_object_get(req, "address");
|
||||
@@ -200,7 +302,16 @@ void cmd_dr_ping(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
// set device address
|
||||
/*
|
||||
* command: dr_setaddress
|
||||
* description: set new address for device
|
||||
*
|
||||
* request format: { "command": "dr_setaddress", "address": <current_address>, "newaddress": <new_address> }
|
||||
* response format: { "success": true/false }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dr_setaddress(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jaddr = json_object_object_get(req, "address");
|
||||
@@ -228,6 +339,16 @@ void cmd_dr_setaddress(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* command: dr_setcalibration
|
||||
* description: set calibration value for device
|
||||
*
|
||||
* request format: { "command": "dr_setcalibration", "address": <address>, "calibration": <calibration_value> }
|
||||
* response format: { "success": true/false }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dr_setcalibration(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jaddr = json_object_object_get(req, "address");
|
||||
@@ -255,6 +376,16 @@ void cmd_dr_setcalibration(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* command: dr_reset
|
||||
* description: reset device at address
|
||||
*
|
||||
* request format: { "command": "dr_reset", "address": <address> }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dr_reset(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jaddr = json_object_object_get(req, "address");
|
||||
@@ -270,6 +401,16 @@ void cmd_dr_reset(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* command: dr_display
|
||||
* description: set display flap at address
|
||||
*
|
||||
* request format: { "command": "dr_display", "address": <address>, "flap": <flap_id>, "full": <true/false> }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dr_display(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jaddr = json_object_object_get(req, "address");
|
||||
@@ -303,6 +444,16 @@ void cmd_dr_display(json_object *req, json_object *res)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* command: dr_power
|
||||
* description: set motor power state at address
|
||||
*
|
||||
* request format: { "command": "dr_power", "address": <address>, "power": <true/false> }
|
||||
* response format: { "ack": true }
|
||||
*
|
||||
* @param req: json request object
|
||||
* @param res: json response object
|
||||
*/
|
||||
void cmd_dr_power(json_object *req, json_object *res)
|
||||
{
|
||||
json_object *jaddr = json_object_object_get(req, "address");
|
||||
@@ -332,7 +483,13 @@ void cmd_dr_power(json_object *req, json_object *res)
|
||||
}
|
||||
|
||||
|
||||
// command parser
|
||||
/*
|
||||
* Command parser for wsserver.
|
||||
* Parses incoming json commands and executes corresponding functions.
|
||||
*
|
||||
* @param req: json request object
|
||||
* @return json response object
|
||||
*/
|
||||
json_object *parse_command(json_object *req)
|
||||
{
|
||||
json_object *commandObj;
|
||||
@@ -425,12 +582,16 @@ json_object *parse_command(json_object *req)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void start_console(int _fd)
|
||||
/*
|
||||
* Start console with webserver and device manager
|
||||
*
|
||||
* @param _fd: rs485 file descriptor
|
||||
* @param configFile: path to device manager config file
|
||||
*/
|
||||
void start_console(int _fd, char *configFile)
|
||||
{
|
||||
fd = _fd;
|
||||
// init device manager
|
||||
devicemgr_init(fd);
|
||||
// start server
|
||||
start_webserver(&parse_command);
|
||||
device_config_file = configFile; // set config file path
|
||||
fd = _fd; // set rs485 file descriptor
|
||||
devicemgr_init(fd); // init device manager
|
||||
start_webserver(&parse_command); // start webserver with command parser
|
||||
}
|
||||
@@ -17,57 +17,64 @@
|
||||
|
||||
enum SFDEVICE_STATE
|
||||
{
|
||||
UNALLOCATED,
|
||||
NEW,
|
||||
OFFLINE,
|
||||
ONLINE,
|
||||
FAILED,
|
||||
REMOVED
|
||||
UNALLOCATED, // device slot not allocated
|
||||
NEW, // device slot allocated, but is not yet refreshed
|
||||
OFFLINE, // device is allocated, but not reachable
|
||||
ONLINE, // device is online and reachable
|
||||
FAILED, // device is online, but in fail-safe mode
|
||||
REMOVED // device has been removed and can be reallocated
|
||||
};
|
||||
enum SFDEVICE_POWER
|
||||
{
|
||||
DISABLED,
|
||||
ENABLED,
|
||||
UNKNOWN
|
||||
DISABLED, // motor power disabled
|
||||
ENABLED, // motor power enabled
|
||||
UNKNOWN // power state unknown (device offline)
|
||||
};
|
||||
|
||||
|
||||
struct SFDEVICE
|
||||
{
|
||||
int pos_x;
|
||||
int pos_y;
|
||||
u_int16_t address;
|
||||
u_int16_t calibration;
|
||||
int rs485_descriptor;
|
||||
double reg_voltage;
|
||||
u_int32_t reg_counter;
|
||||
u_int8_t reg_status;
|
||||
u_int8_t current_flap;
|
||||
enum SFDEVICE_STATE deviceState;
|
||||
enum SFDEVICE_POWER powerState;
|
||||
int pos_x; // position in matrix
|
||||
int pos_y; // position in matrix
|
||||
u_int16_t address; // device address
|
||||
u_int16_t calibration; // calibration offset value
|
||||
int rs485_descriptor; // rs485 file descriptor
|
||||
double reg_voltage; // last read voltage
|
||||
u_int32_t reg_counter; // last rotation counter
|
||||
u_int8_t reg_status; // last status register
|
||||
u_int8_t current_flap; // current flap position
|
||||
enum SFDEVICE_STATE deviceState; // device state
|
||||
enum SFDEVICE_POWER powerState; // power state
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SFDEVICE_MAXDEV = 128,
|
||||
SFDEVICE_MAX_X = 20,
|
||||
SFDEVICE_MAX_Y = 4,
|
||||
JSON_MAX_LINE_LEN = 256
|
||||
SFDEVICE_MAXDEV = 128, // maximum number of devices supported
|
||||
SFDEVICE_MAX_X = 20, // maximum x size of device matrix
|
||||
SFDEVICE_MAX_Y = 4, // maximum y size of device matrix
|
||||
JSON_MAX_LINE_LEN = 256 // maximum length of a line in json file
|
||||
};
|
||||
|
||||
// next free slot to register device
|
||||
int nextFreeSlot = -1;
|
||||
int deviceMap[SFDEVICE_MAX_X][SFDEVICE_MAX_Y];
|
||||
int deviceFd;
|
||||
struct SFDEVICE devices[SFDEVICE_MAXDEV];
|
||||
|
||||
int nextFreeSlot = -1; // next free slot in device array
|
||||
int deviceMap[SFDEVICE_MAX_X][SFDEVICE_MAX_Y]; // device map matrix
|
||||
int deviceFd; // rs485 file descriptor
|
||||
struct SFDEVICE devices[SFDEVICE_MAXDEV]; // device array
|
||||
|
||||
// symbol table for flap characters
|
||||
const char *symbols[45] = {" ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
||||
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Ä", "Ö", "Ü",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ".", "-", "?", "!"};
|
||||
|
||||
/*
|
||||
* Initialize device manager.
|
||||
* Clear device map and set all devices as unallocated
|
||||
*
|
||||
* @param fd rs485 file descriptor
|
||||
*/
|
||||
void devicemgr_init(int fd)
|
||||
{
|
||||
deviceFd = fd;
|
||||
deviceFd = fd; // store rs485 file descriptor
|
||||
// reserve memory buffer
|
||||
for (int y = 0; y < SFDEVICE_MAX_Y; y++)
|
||||
{
|
||||
@@ -79,10 +86,15 @@ void devicemgr_init(int fd)
|
||||
for (int ix = 0; ix < SFDEVICE_MAXDEV; ix++)
|
||||
{
|
||||
devices[ix].address = 0; // Adress 0 is only used for new units. should never be used for active unit
|
||||
devices[ix].deviceState = UNALLOCATED;
|
||||
devices[ix].deviceState = UNALLOCATED; // mark all devices as unallocated
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read status from device and store it in device struct
|
||||
* Returns 0 on success, -1 on read error, -2 if device not defined
|
||||
*
|
||||
* @param device_id ID of device to read
|
||||
*/
|
||||
int devicemgr_readStatus(int device_id)
|
||||
{
|
||||
if (devices[device_id].address > 0)
|
||||
@@ -92,22 +104,22 @@ int devicemgr_readStatus(int device_id)
|
||||
u_int8_t _status =
|
||||
sfbus_read_status(devices[device_id].rs485_descriptor, devices[device_id].address, &_voltage, &_counter);
|
||||
|
||||
if (_status == 0xFF)
|
||||
if (_status == 0xFF) // error reading status
|
||||
{
|
||||
devices[device_id].powerState = UNKNOWN;
|
||||
devices[device_id].deviceState = OFFLINE;
|
||||
return -1;
|
||||
}
|
||||
devices[device_id].reg_voltage = _voltage;
|
||||
devices[device_id].reg_voltage = _voltage; // store read values
|
||||
devices[device_id].reg_counter = _counter;
|
||||
devices[device_id].reg_status = _status;
|
||||
devices[device_id].powerState = ~((devices[device_id].reg_status >> 4)) & 0x01;
|
||||
devices[device_id].deviceState = ONLINE;
|
||||
if ((((devices[device_id].reg_status) >> 5) & 0x01) > 0)
|
||||
if ((((devices[device_id].reg_status) >> 5) & 0x01) > 0) // fail safe active
|
||||
{
|
||||
devices[device_id].deviceState = FAILED;
|
||||
}
|
||||
return 0;
|
||||
return 0; // success
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -115,6 +127,12 @@ int devicemgr_readStatus(int device_id)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read calibration data from device and store it in device struct
|
||||
* Returns 0 on success, -1 on read error, -2 if device not online
|
||||
*
|
||||
* @param device_id ID of device to read
|
||||
*/
|
||||
int devicemgr_readCalib(int device_id)
|
||||
{
|
||||
if (devices[device_id].deviceState == ONLINE)
|
||||
@@ -139,6 +157,11 @@ int devicemgr_readCalib(int device_id)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate json object with device map
|
||||
*
|
||||
* @return json object with device map
|
||||
*/
|
||||
json_object *devicemgr_printMap()
|
||||
{
|
||||
json_object *rows_array = json_object_new_array();
|
||||
@@ -154,6 +177,12 @@ json_object *devicemgr_printMap()
|
||||
return rows_array;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate json object with device details
|
||||
*
|
||||
* @param device_id ID of device to print
|
||||
* @param root json object to add details to
|
||||
*/
|
||||
void devicemgr_printDetails(int device_id, json_object *root)
|
||||
{
|
||||
// generate json object with status
|
||||
@@ -172,7 +201,7 @@ void devicemgr_printDetails(int device_id, json_object *root)
|
||||
json_object_object_add(status, "rotations", json_object_new_int(devices[device_id].reg_counter));
|
||||
json_object_object_add(status, "power", json_object_new_boolean(devices[device_id].powerState));
|
||||
json_object_object_add(status, "raw", json_object_new_uint64(devices[device_id].reg_status));
|
||||
switch (devices[device_id].deviceState)
|
||||
switch (devices[device_id].deviceState) // device state
|
||||
{
|
||||
case ONLINE:
|
||||
json_object_object_add(status, "device", json_object_new_string("ONLINE"));
|
||||
@@ -193,7 +222,7 @@ void devicemgr_printDetails(int device_id, json_object *root)
|
||||
json_object_object_add(status, "device", json_object_new_string("UNALLOCATED"));
|
||||
break;
|
||||
}
|
||||
json_object *status_flags = json_object_new_object();
|
||||
json_object *status_flags = json_object_new_object(); // status flags
|
||||
json_object_object_add(status_flags,
|
||||
"errorTooBig",
|
||||
json_object_new_boolean(((devices[device_id].reg_status) >> 0) & 0x01));
|
||||
@@ -219,6 +248,11 @@ void devicemgr_printDetails(int device_id, json_object *root)
|
||||
json_object_object_add(root, "status", status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate json object with details for all valid devices
|
||||
*
|
||||
* @param root json object to add details to
|
||||
*/
|
||||
void devicemgr_printDetailsAll(json_object *root)
|
||||
{
|
||||
json_object_object_add(root, "devices_all", json_object_new_int(nextFreeSlot + 1));
|
||||
@@ -243,6 +277,12 @@ void devicemgr_printDetailsAll(json_object *root)
|
||||
json_object_object_add(root, "devices_online", json_object_new_int(devices_online));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set single device to flap character
|
||||
*
|
||||
* @param id ID of device to set
|
||||
* @param flap character to set
|
||||
*/
|
||||
void setSingle(int id, char flap)
|
||||
{
|
||||
// first convert char to flap id
|
||||
@@ -260,12 +300,25 @@ void setSingle(int id, char flap)
|
||||
}
|
||||
}
|
||||
|
||||
void setSingleRaw(int id, int flap)
|
||||
/*
|
||||
* Set single device to raw flap ID
|
||||
*
|
||||
* @param id ID of device to set
|
||||
* @param flap flap ID to set
|
||||
*/
|
||||
void devicemgr_setSingleRaw(int id, int flap)
|
||||
{
|
||||
sfbus_display_full(devices[id].rs485_descriptor, devices[id].address, flap);
|
||||
devices[id].current_flap = flap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print text to device matrix starting at position (x,y)
|
||||
*
|
||||
* @param text text to print
|
||||
* @param x x position to start printing
|
||||
* @param y y position to start printing
|
||||
*/
|
||||
void devicemgr_printText(const char *text, int x, int y)
|
||||
{
|
||||
for (int i = 0; i < strlen(text); i++)
|
||||
@@ -280,16 +333,25 @@ void devicemgr_printText(const char *text, int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print char to device matrix at position (x,y)
|
||||
*
|
||||
* @param flap flap ID to print
|
||||
* @param x x position to print
|
||||
* @param y y position to print
|
||||
*/
|
||||
void devicemgr_printFlap(int flap, int x, int y)
|
||||
{
|
||||
int this_id = deviceMap[x][y];
|
||||
if (this_id >= 0)
|
||||
{
|
||||
setSingleRaw(this_id, flap);
|
||||
devicemgr_setSingleRaw(this_id, flap);
|
||||
}
|
||||
}
|
||||
|
||||
// clears complete screen
|
||||
/*
|
||||
* Clear all devices in matrix (set to flap 0)
|
||||
*/
|
||||
void devicemgr_clearscreen()
|
||||
{
|
||||
for (int ix = 0; ix < SFDEVICE_MAXDEV; ix++)
|
||||
@@ -298,12 +360,22 @@ void devicemgr_clearscreen()
|
||||
{
|
||||
if (devices[ix].current_flap != 0)
|
||||
{
|
||||
setSingleRaw(ix, 0);
|
||||
devicemgr_setSingleRaw(ix, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Register new device in device manager and add it to device map
|
||||
*
|
||||
* @param rs485_descriptor rs485 file descriptor
|
||||
* @param address device address
|
||||
* @param x x position in device matrix
|
||||
* @param y y position in device matrix
|
||||
* @param nid optional device ID to use (set to -1 to auto assign)
|
||||
* @return device ID assigned
|
||||
*/
|
||||
int devicemgr_register(int rs485_descriptor, u_int16_t address, int x, int y, int nid)
|
||||
{
|
||||
if (nid < 0)
|
||||
@@ -337,7 +409,11 @@ int devicemgr_register(int rs485_descriptor, u_int16_t address, int x, int y, in
|
||||
return nid;
|
||||
}
|
||||
|
||||
// refreshes status of all devices
|
||||
/*
|
||||
* Refresh all devices and update their status
|
||||
*
|
||||
* @return number of online devices
|
||||
*/
|
||||
int devicemgr_refresh()
|
||||
{
|
||||
int devices_online = 0;
|
||||
@@ -355,7 +431,11 @@ int devicemgr_refresh()
|
||||
return devices_online;
|
||||
}
|
||||
|
||||
// remove devices from system
|
||||
/*
|
||||
* Remove device from device manager
|
||||
*
|
||||
* @param id ID of device to remove
|
||||
*/
|
||||
int devicemgr_remove(int id)
|
||||
{
|
||||
devices[nextFreeSlot].deviceState = REMOVED;
|
||||
@@ -364,6 +444,12 @@ int devicemgr_remove(int id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save device manager configuration to json file
|
||||
*
|
||||
* @param file path to json file
|
||||
* @return 0 on success
|
||||
*/
|
||||
int devicemgr_save(char *file)
|
||||
{
|
||||
json_object *root = json_object_new_object();
|
||||
@@ -388,8 +474,16 @@ int devicemgr_save(char *file)
|
||||
fptr = fopen(file, "w");
|
||||
fwrite(data, sizeof(char), strlen(data), fptr);
|
||||
fclose(fptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load device manager configuration from json file and parse contents
|
||||
* Verify all required keys are present and refresh device status
|
||||
*
|
||||
* @param file path to json file
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int devicemgr_load(char *file)
|
||||
{
|
||||
FILE *fptr;
|
||||
@@ -465,6 +559,13 @@ int devicemgr_load(char *file)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Load single device from json object and register it
|
||||
* Verify all required keys are present
|
||||
*
|
||||
* @param device_obj json object with device data
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int devicemgr_load_single(json_object *device_obj)
|
||||
{
|
||||
json_object *jid = json_object_object_get(device_obj, "id");
|
||||
|
||||
@@ -12,6 +12,8 @@ const char *loglevel[] = {"TRACE","DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL
|
||||
void init_logger(int log_level)
|
||||
{
|
||||
log_level_global = log_level;
|
||||
log_message(LOG_INFO, "Set log level to %s", loglevel[log_level_global]);
|
||||
|
||||
}
|
||||
|
||||
void log_message(int level, const char *message, ...)
|
||||
|
||||
@@ -32,19 +32,17 @@ void printUsage(char *argv[])
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
// initialize logger
|
||||
init_logger(LOG_TRACE);
|
||||
log_message(LOG_INFO, "Starting split-flap pc client %s", "v1.0.0");
|
||||
log_message(LOG_INFO, "(c) 2024-2025 GuniaLabs (www.dennisgunia.de)");
|
||||
|
||||
// parse arguments
|
||||
int opt = ' ';
|
||||
u_int16_t addr_int = 0;
|
||||
char *port = malloc(256);
|
||||
char *command = malloc(16);
|
||||
char *addr = malloc(16);
|
||||
char *data = malloc(256);
|
||||
command = "";
|
||||
addr = "";
|
||||
data = "";
|
||||
while ((opt = getopt(argc, argv, "p:c:a:d:")) != -1)
|
||||
char *port, *config_file, *log_level;
|
||||
|
||||
while ((opt = getopt(argc, argv, "p:c:l:")) != -1) // check options
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
@@ -52,128 +50,78 @@ int main(int argc, char *argv[])
|
||||
port = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
command = optarg;
|
||||
config_file = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
addr = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
data = optarg;
|
||||
case 'l':
|
||||
log_level = optarg;
|
||||
break;
|
||||
default:
|
||||
printUsage(argv);
|
||||
}
|
||||
}
|
||||
if (access(port, F_OK) != 0)
|
||||
|
||||
|
||||
if (log_level != NULL) // if log level specified
|
||||
{
|
||||
log_message(LOG_CRITICAL, "Filedescriptor: %s does not exist or cannot be opened\n", port);
|
||||
printUsage(argv);
|
||||
if (strlen(log_level) > 0)
|
||||
{ // if log level specified
|
||||
long inputLogLevel = strtol("", NULL, 10); // parse log level
|
||||
init_logger(inputLogLevel); // re-init logger with new level
|
||||
}
|
||||
// parse address
|
||||
if (strlen(addr) == 0)
|
||||
}
|
||||
|
||||
if (config_file == NULL) // if config file not specified
|
||||
{
|
||||
log_message(LOG_CRITICAL, "Please specify address\n");
|
||||
log_message(LOG_CRITICAL, "Please specify config file\n");
|
||||
printUsage(argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr_int = strtol(addr, NULL, 10);
|
||||
if (strlen(config_file) == 0) // if config file path empty
|
||||
{
|
||||
log_message(LOG_CRITICAL, "Please specify config file\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (access(config_file, F_OK) != 0) // check if config file exists and can be opened
|
||||
{
|
||||
log_message(LOG_CRITICAL, "Config file: %s does not exist or cannot be opened\n", config_file);
|
||||
printUsage(argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_INFO, "Use device configuration at '%s'", config_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start program
|
||||
setvbuf(stdout, NULL, _IONBF, 0); // do not buffer stdout!!!!
|
||||
if (port == NULL) // if port not specified
|
||||
{
|
||||
log_message(LOG_CRITICAL, "Please specify serial port\n");
|
||||
printUsage(argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(port) == 0) // if port path empty
|
||||
{
|
||||
log_message(LOG_CRITICAL, "Please specify serial port\n");
|
||||
printUsage(argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (access(port, F_OK) != 0) // check if port exists and can be opened
|
||||
{
|
||||
log_message(LOG_CRITICAL, "Serial port: %s does not exist or cannot be opened\n", port);
|
||||
printUsage(argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_INFO, "Use serial port at '%s'", port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_message(LOG_INFO,"Open device at %s @ 57600 Baud", port);
|
||||
int fd = rs485_init(port, B57600); // setup rs485
|
||||
|
||||
if (strcmp(command, "ping") == 0)
|
||||
{
|
||||
sfbus_ping(fd, addr_int);
|
||||
}
|
||||
else if (strcmp(command, "printf") == 0)
|
||||
{
|
||||
devicemgr_printText(data, 0, 0);
|
||||
}
|
||||
else if (strcmp(command, "r_eeprom") == 0)
|
||||
{
|
||||
char *buffer = malloc(64);
|
||||
sfbus_read_eeprom(fd, addr_int, buffer);
|
||||
printf("Read data: 0x");
|
||||
print_charHex(buffer, 5);
|
||||
printf("\n");
|
||||
free(buffer);
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(command, "w_addr") == 0)
|
||||
{
|
||||
int n_addr = strtol(data, NULL, 10);
|
||||
int ret = sfbusu_write_address(fd, addr_int, n_addr);
|
||||
exit(ret);
|
||||
}
|
||||
else if (strcmp(command, "w_cal") == 0)
|
||||
{
|
||||
int n_addr = strtol(data, NULL, 10);
|
||||
int ret = sfbusu_write_calibration(fd, addr_int, n_addr);
|
||||
exit(ret);
|
||||
}
|
||||
else if (strcmp(command, "status") == 0)
|
||||
{
|
||||
double voltage = 0;
|
||||
u_int32_t counter = 0;
|
||||
u_int8_t status = sfbus_read_status(fd, addr_int, &voltage, &counter);
|
||||
printf("=======================\n");
|
||||
printf("Status register flags :\n");
|
||||
printf(" 00 -> errorTooBig : %i\n", (status >> 0) & 0x01);
|
||||
printf(" 01 -> noHome : %i\n", (status >> 1) & 0x01);
|
||||
printf(" 02 -> fuseBlown : %i\n", (status >> 2) & 0x01);
|
||||
printf(" 03 -> homeSense : %i\n", (status >> 3) & 0x01);
|
||||
printf(" 04 -> powerDown : %i\n", (status >> 4) & 0x01);
|
||||
printf(" 05 -> failSafe : %i\n", (status >> 5) & 0x01);
|
||||
printf(" 06 -> busy : %i\n", (status >> 6) & 0x01);
|
||||
printf("Driver-Voltage : %.2fV\n", voltage);
|
||||
printf("Rotations : %i\n", counter);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(command, "display") == 0)
|
||||
{
|
||||
int flap = strtol(data, NULL, 10);
|
||||
// read current eeprom status
|
||||
char *buffer_w = malloc(4);
|
||||
sfbus_display(fd, addr_int, flap);
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(command, "display_fr") == 0)
|
||||
{
|
||||
int flap = strtol(data, NULL, 10);
|
||||
// read current eeprom status
|
||||
char *buffer_w = malloc(4);
|
||||
sfbus_display_full(fd, addr_int, flap);
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(command, "reset") == 0)
|
||||
{
|
||||
sfbus_reset_device(fd, addr_int);
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(command, "power_on") == 0)
|
||||
{
|
||||
sfbus_motor_power(fd, addr_int, 1);
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(command, "power_off") == 0)
|
||||
{
|
||||
sfbus_motor_power(fd, addr_int, 0);
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(command, "server") == 0)
|
||||
{
|
||||
start_console(fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Invalid command specified!\n");
|
||||
printUsage(argv);
|
||||
}
|
||||
start_console(fd, config_file); // start console
|
||||
return 0;
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "ftdi485.h"
|
||||
#include "logging/logger.h"
|
||||
#include "../logging/logger.h"
|
||||
|
||||
/*
|
||||
* Open RS485 Interface (FT232RL)
|
||||
@@ -8,12 +8,18 @@
|
||||
*/
|
||||
|
||||
#include "sfbus.h"
|
||||
#include "logging/logger.h"
|
||||
#include "../logging/logger.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/*
|
||||
* Print buffer as hex values to stdout
|
||||
* Used for debugging purposes
|
||||
*
|
||||
* @param buffer: buffer to print
|
||||
* @param length: length of buffer
|
||||
*/
|
||||
void print_charHex(char *buffer, int length)
|
||||
{
|
||||
int _tlength = length;
|
||||
@@ -25,26 +31,51 @@ void print_charHex(char *buffer, int length)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print received buffer as hex values to stdout
|
||||
* Used for debugging purposes
|
||||
*
|
||||
* @param buffer: buffer to print
|
||||
* @param length: length of buffer
|
||||
* @param address: device address
|
||||
*/
|
||||
void print_bufferHexRx(char *buffer, int length, u_int16_t address)
|
||||
{
|
||||
if (log_message_header(LOG_TRACE) > 0)
|
||||
{
|
||||
printf("Rx (0x%04X): ", address);
|
||||
printf("Rx at address: 0x%04X Data: ", address);
|
||||
print_charHex(buffer, length);
|
||||
printf("| %i bytes received\n", length);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print transmitted buffer as hex values to stdout
|
||||
* Used for debugging purposes
|
||||
*
|
||||
* @param buffer: buffer to print
|
||||
* @param length: length of buffer
|
||||
* @param address: device address
|
||||
*/
|
||||
void print_bufferHexTx(char *buffer, int length, u_int16_t address)
|
||||
{
|
||||
if (log_message_header(LOG_TRACE) > 0)
|
||||
{
|
||||
printf("Tx (0x%04X): ", address);
|
||||
printf("Tx at address: 0x%04X Data: ", address);
|
||||
print_charHex(buffer, length);
|
||||
printf("| %i bytes sent\n", length);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive SFBus frame with protocol version 2.0 and wait for valid data
|
||||
* Fails after 2 unsuccessful attempts
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param buffer: buffer to store received data
|
||||
* @return length of received data on success, -1 on error
|
||||
*/
|
||||
ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
@@ -63,6 +94,15 @@ ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer)
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive SFBus frame with protocol version 2.0
|
||||
* Handles start byte, address check and CRC verification
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param buffer: buffer to store received data
|
||||
* @return length of received data on success, -1 on error
|
||||
*/
|
||||
ssize_t sfbus_recv_frame_v2(int fd, u_int16_t address, char *buffer)
|
||||
{
|
||||
|
||||
@@ -123,7 +163,13 @@ ssize_t sfbus_recv_frame_v2(int fd, u_int16_t address, char *buffer)
|
||||
}
|
||||
|
||||
/*
|
||||
* Send SFBus frame with protocol version 2.0 and calculated CRC
|
||||
* Send SFBus frame with protocol version 2.0
|
||||
* Generates frame with start byte, address and crc checksum
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param length: length of payload
|
||||
* @param buffer: payload buffer to send
|
||||
*/
|
||||
void sfbus_send_frame_v2(int fd, u_int16_t address, u_int8_t length, char *buffer)
|
||||
{
|
||||
@@ -150,8 +196,11 @@ void sfbus_send_frame_v2(int fd, u_int16_t address, u_int8_t length, char *buffe
|
||||
}
|
||||
|
||||
/*
|
||||
* Send ping to device at specified address.
|
||||
* returns 0 on success, else 1.
|
||||
* Send ping command to device and wait for response
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @return 0 on success, 1 on failure
|
||||
*/
|
||||
int sfbus_ping(int fd, u_int16_t address)
|
||||
{
|
||||
@@ -173,6 +222,15 @@ int sfbus_ping(int fd, u_int16_t address)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data from device EEPROM
|
||||
* Verifies received data and checks for ACK byte
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param buffer: buffer to store received data
|
||||
* @return length of received data on success, -1 on error
|
||||
*/
|
||||
int sfbus_read_eeprom(int fd, u_int16_t address, char *buffer)
|
||||
{
|
||||
char *cmd = "\xF0";
|
||||
@@ -195,6 +253,16 @@ int sfbus_read_eeprom(int fd, u_int16_t address, char *buffer)
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to device EEPROM
|
||||
* Verifies received data and checks for ACK byte
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param wbuffer: buffer with data to write
|
||||
* @param rbuffer: buffer to store received data
|
||||
* @return length of received data on success, -1 on error
|
||||
*/
|
||||
int sfbus_write_eeprom(int fd, u_int16_t address, char *wbuffer, char *rbuffer)
|
||||
{
|
||||
char *cmd = malloc(5);
|
||||
@@ -221,6 +289,14 @@ int sfbus_write_eeprom(int fd, u_int16_t address, char *wbuffer, char *rbuffer)
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send display command to device to set flap position
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param flap: flap ID to set
|
||||
* @return 0 on success
|
||||
*/
|
||||
int sfbus_display(int fd, u_int16_t address, u_int8_t flap)
|
||||
{
|
||||
char *cmd = malloc(5);
|
||||
@@ -231,6 +307,14 @@ int sfbus_display(int fd, u_int16_t address, u_int8_t flap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send display command to device to set flap position with full rotation
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param flap: flap ID to set
|
||||
* @return 0 on success
|
||||
*/
|
||||
int sfbus_display_full(int fd, u_int16_t address, u_int8_t flap)
|
||||
{
|
||||
char *cmd = malloc(5);
|
||||
@@ -241,6 +325,15 @@ int sfbus_display_full(int fd, u_int16_t address, u_int8_t flap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read device status including voltage operation counter and status flags
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param voltage: pointer to store read voltage value
|
||||
* @param counter: pointer to store read operation counter value
|
||||
* @return status byte on success, 0xFF on error
|
||||
*/
|
||||
u_int8_t sfbus_read_status(int fd, u_int16_t address, double *voltage, u_int32_t *counter)
|
||||
{
|
||||
char *cmd = "\xF8";
|
||||
@@ -260,17 +353,30 @@ u_int8_t sfbus_read_status(int fd, u_int16_t address, double *voltage, u_int32_t
|
||||
|
||||
*voltage = __voltage;
|
||||
*counter = (u_int32_t)_counter;
|
||||
|
||||
free(_buffer);
|
||||
return 0x00;
|
||||
u_int8_t status = *(_buffer + 0) & 0xFF; // store status byte temporarily
|
||||
free(_buffer); // free rx buffer to prevent memory leak
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset device
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
*/
|
||||
void sfbus_reset_device(int fd, u_int16_t address)
|
||||
{
|
||||
char *cmd = "\x30";
|
||||
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable motor power on device
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param state: 0 = disable power, >0 = enable power
|
||||
*/
|
||||
void sfbus_motor_power(int fd, u_int16_t address, u_int8_t state)
|
||||
{
|
||||
char *cmd = "\x20";
|
||||
@@ -281,6 +387,14 @@ void sfbus_motor_power(int fd, u_int16_t address, u_int8_t state)
|
||||
sfbus_send_frame_v2(fd, address, 1, cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to calculate CRC16 checksum
|
||||
* Used for SFBus protocol v2.0
|
||||
*
|
||||
* @param buffer: buffer to calculate checksum for
|
||||
* @param len: length of buffer
|
||||
* @return calculated CRC16 checksum
|
||||
*/
|
||||
u_int16_t calc_CRC16(char *buffer, u_int8_t len)
|
||||
{
|
||||
u_int16_t crc16 = 0xFFFF;
|
||||
@@ -10,6 +10,14 @@
|
||||
#include "sfbus-util.h"
|
||||
#include "logging/logger.h"
|
||||
|
||||
/*
|
||||
* Write new address to device
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param current: current device address
|
||||
* @param new: new device address
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int sfbusu_write_address(int fd, u_int16_t current, u_int16_t new)
|
||||
{
|
||||
log_message(LOG_INFO, "Writing new address 0x%04X to device with current address 0x%04X", new, current);
|
||||
@@ -37,6 +45,14 @@ int sfbusu_write_address(int fd, u_int16_t current, u_int16_t new)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write new calibration data to device
|
||||
*
|
||||
* @param fd: rs485 file descriptor
|
||||
* @param address: device address
|
||||
* @param data: calibration data
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int sfbusu_write_calibration(int fd, u_int16_t address, u_int16_t data)
|
||||
{
|
||||
log_message(LOG_INFO, "Writing new calibration 0x%04X to device at address 0x%04X", data, address);
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
json_object *(*commandparser_func)(json_object *);
|
||||
|
||||
// this sections handles ws connections and communications
|
||||
// called on opening websocket client
|
||||
|
||||
/*
|
||||
* called on opening websocket client
|
||||
* @param client: websocket client connection
|
||||
*/
|
||||
void ws_opencon(ws_cli_conn_t client)
|
||||
{
|
||||
char *cli;
|
||||
@@ -25,7 +29,10 @@ void ws_opencon(ws_cli_conn_t client)
|
||||
log_message(LOG_DEBUG, "WebSocket connection opened, addr: %s", cli);
|
||||
}
|
||||
|
||||
// called on closing websocket client
|
||||
/*
|
||||
* called on closing websocket client
|
||||
* @param client: websocket client connection
|
||||
*/
|
||||
void ws_closecon(ws_cli_conn_t client)
|
||||
{
|
||||
char *cli;
|
||||
@@ -33,7 +40,15 @@ void ws_closecon(ws_cli_conn_t client)
|
||||
log_message(LOG_DEBUG, "WebSocket connection closed, addr: %s", cli);
|
||||
}
|
||||
|
||||
// called on receiving websocket message
|
||||
/*
|
||||
* called on receiving websocket message
|
||||
* Handles incoming websocket messages, parses json commands and sends responses.
|
||||
*
|
||||
* @param client: websocket client connection
|
||||
* @param msg: received message
|
||||
* @param size: size of received message
|
||||
* @param type: type of message
|
||||
*/
|
||||
void ws_messagehandler(ws_cli_conn_t client, const unsigned char *msg, uint64_t size, int type)
|
||||
{
|
||||
char *cli = ws_getaddress(client);
|
||||
@@ -76,12 +91,25 @@ void ws_messagehandler(ws_cli_conn_t client, const unsigned char *msg, uint64_t
|
||||
free(tok); // always free tokenizer, to prevent memory leak
|
||||
}
|
||||
|
||||
/*
|
||||
* send json response to websocket client
|
||||
*
|
||||
* @param client: websocket client connection
|
||||
* @param res: json response object
|
||||
*/
|
||||
void send_json_response(ws_cli_conn_t client, json_object *res)
|
||||
{
|
||||
const char *message = json_object_to_json_string_ext(res, JSON_C_TO_STRING_PRETTY);
|
||||
ws_sendframe_txt(client, message);
|
||||
}
|
||||
|
||||
/*
|
||||
* send json error to websocket client
|
||||
*
|
||||
* @param client: websocket client connection
|
||||
* @param error: error message
|
||||
* @param detail: error detail message
|
||||
*/
|
||||
void send_json_error(ws_cli_conn_t client, char *error, const char *detail)
|
||||
{
|
||||
json_object *root = json_object_new_object();
|
||||
@@ -90,7 +118,12 @@ void send_json_error(ws_cli_conn_t client, char *error, const char *detail)
|
||||
send_json_response(client, root);
|
||||
}
|
||||
|
||||
// starting webserver
|
||||
/*
|
||||
* Start websocket server
|
||||
*
|
||||
* @param commandparser_func_ptr: pointer to command parser function
|
||||
* @return 0 on success
|
||||
*/
|
||||
int start_webserver(json_object *(*commandparser_func_ptr)(json_object *))
|
||||
{
|
||||
commandparser_func = commandparser_func_ptr;
|
||||
|
||||
Reference in New Issue
Block a user