add protocol version2
This commit is contained in:
BIN
dist/controller_schematics_rev0.pdf
vendored
Normal file
BIN
dist/controller_schematics_rev0.pdf
vendored
Normal file
Binary file not shown.
BIN
dist/controller_schematics_rev2.pdf
vendored
Normal file
BIN
dist/controller_schematics_rev2.pdf
vendored
Normal file
Binary file not shown.
@@ -6,25 +6,25 @@
|
|||||||
* https://github.com/dennis9819/splitflap_v1
|
* https://github.com/dennis9819/splitflap_v1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/iom8.h>
|
||||||
|
#include <avr/wdt.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/wdt.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
#include <avr/iom8.h>
|
|
||||||
|
|
||||||
|
|
||||||
// I/O Pin definition
|
// I/O Pin definition
|
||||||
#define BUX_RX PD0 // RX Pin (to buffer)
|
#define BUX_RX PD0 // RX Pin (to buffer)
|
||||||
#define BUX_TX PD1 // TX Pin (to buffer)
|
#define BUX_TX PD1 // TX Pin (to buffer)
|
||||||
#define BUX_DIR PD2 // Buffer direction pin
|
#define BUX_DIR PD2 // Buffer direction pin
|
||||||
#define SENSOR_HOME PD3 // Home sensor pin
|
#define SENSOR_HOME PD3 // Home sensor pin
|
||||||
|
|
||||||
#define MOTOR_A PC0 // Motor phase A driver
|
#define MOTOR_A PC0 // Motor phase A driver
|
||||||
#define MOTOR_B PC1 // Motor phase B driver
|
#define MOTOR_B PC1 // Motor phase B driver
|
||||||
#define MOTOR_C PC2 // Motor phase C driver
|
#define MOTOR_C PC2 // Motor phase C driver
|
||||||
#define MOTOR_D PC3 // Motor phase D driver
|
#define MOTOR_D PC3 // Motor phase D driver
|
||||||
|
|
||||||
// EEPROM Addresses
|
// EEPROM Addresses
|
||||||
#define CONF_CONST_OKAY (uint8_t)0xAA
|
#define CONF_CONST_OKAY (uint8_t)0xAA
|
||||||
@@ -33,23 +33,23 @@
|
|||||||
#define CONF_ADDR_OFFSET 0x0002
|
#define CONF_ADDR_OFFSET 0x0002
|
||||||
|
|
||||||
// Protocol definitions
|
// Protocol definitions
|
||||||
#define PROTO_MAXPKGLEN 64 // maximum size of package in bytes
|
#define PROTO_MAXPKGLEN 64 // maximum size of package in bytes
|
||||||
|
|
||||||
// Command Bytes
|
// Command Bytes
|
||||||
#define CMDB_SETVAL (uint8_t)0x10 // Set display value
|
#define CMDB_SETVAL (uint8_t)0x10 // Set display value
|
||||||
#define CMDB_SETVALR (uint8_t)0x11 // Set display value and do a full rotation
|
#define CMDB_SETVALR (uint8_t)0x11 // Set display value and do a full rotation
|
||||||
#define CMDB_EEPROMR (uint8_t)0xF0 // Read EEPROM
|
#define CMDB_EEPROMR (uint8_t)0xF0 // Read EEPROM
|
||||||
#define CMDB_EEPROMW (uint8_t)0xF1 // Write EEPROM
|
#define CMDB_EEPROMW (uint8_t)0xF1 // Write EEPROM
|
||||||
#define CMDB_GSTS (uint8_t)0xF8 // Get status
|
#define CMDB_GSTS (uint8_t)0xF8 // Get status
|
||||||
#define CMDB_PING (uint8_t)0xFE // Ping
|
#define CMDB_PING (uint8_t)0xFE // Ping
|
||||||
#define CMDB_RESET (uint8_t)0x30 // Reset device
|
#define CMDB_RESET (uint8_t)0x30 // Reset device
|
||||||
#define CMDB_PWRON (uint8_t)0x21 // Power motor on
|
#define CMDB_PWRON (uint8_t)0x21 // Power motor on
|
||||||
#define CMDB_RPWROFF (uint8_t)0x20 // Poer motor off
|
#define CMDB_RPWROFF (uint8_t)0x20 // Poer motor off
|
||||||
|
|
||||||
// Command Responses
|
// Command Responses
|
||||||
#define CMDR_ERR_INVALID 0xEE // Invalid command
|
#define CMDR_ERR_INVALID 0xEE // Invalid command
|
||||||
#define CMDR_ACK 0xAA // Acknowledge
|
#define CMDR_ACK 0xAA // Acknowledge
|
||||||
#define CMDR_PING 0xFF // Ping response
|
#define CMDR_PING 0xFF // Ping response
|
||||||
|
|
||||||
// Utility definitions
|
// Utility definitions
|
||||||
#define SHIFT_0B 0
|
#define SHIFT_0B 0
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ void initialSetup()
|
|||||||
void readCommand()
|
void readCommand()
|
||||||
{
|
{
|
||||||
char *payload = malloc(PROTO_MAXPKGLEN);
|
char *payload = malloc(PROTO_MAXPKGLEN);
|
||||||
uint8_t payload_len = sfbus_recv_frame(address, payload);
|
uint8_t payload_len = sfbus_recv_frame_v2(address, payload);
|
||||||
|
payload += 2; // skip address bytes
|
||||||
if (payload_len > 0)
|
if (payload_len > 0)
|
||||||
{
|
{
|
||||||
// read command byte
|
// read command byte
|
||||||
@@ -90,7 +91,7 @@ void readCommand()
|
|||||||
*(msg + i) = (char)eeprom_read_c(i - 1);
|
*(msg + i) = (char)eeprom_read_c(i - 1);
|
||||||
}
|
}
|
||||||
_delay_ms(2);
|
_delay_ms(2);
|
||||||
sfbus_send_frame(0xFFFF, msg, bytes + 1);
|
sfbus_send_frame_v2(0xFFFF, msg, bytes + 1);
|
||||||
free(msg);
|
free(msg);
|
||||||
}
|
}
|
||||||
else if (opcode == CMDB_EEPROMW)
|
else if (opcode == CMDB_EEPROMW)
|
||||||
@@ -111,7 +112,7 @@ void readCommand()
|
|||||||
*(msg + i) = (char)eeprom_read_c(i - 1);
|
*(msg + i) = (char)eeprom_read_c(i - 1);
|
||||||
}
|
}
|
||||||
_delay_ms(2);
|
_delay_ms(2);
|
||||||
sfbus_send_frame(0xFFFF, msg, bytes + 1);
|
sfbus_send_frame_v2(0xFFFF, msg, bytes + 1);
|
||||||
free(msg);
|
free(msg);
|
||||||
// now use new addr
|
// now use new addr
|
||||||
uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR);
|
uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR);
|
||||||
@@ -131,14 +132,14 @@ void readCommand()
|
|||||||
*(msg + 4) = (char)((counter >> SHIFT_2B) & 0xFF);
|
*(msg + 4) = (char)((counter >> SHIFT_2B) & 0xFF);
|
||||||
*(msg + 3) = (char)((counter >> SHIFT_3B) & 0xFF);
|
*(msg + 3) = (char)((counter >> SHIFT_3B) & 0xFF);
|
||||||
_delay_ms(2);
|
_delay_ms(2);
|
||||||
sfbus_send_frame(0xFFFF, msg, 7);
|
sfbus_send_frame_v2(0xFFFF, msg, 7);
|
||||||
free(msg);
|
free(msg);
|
||||||
}
|
}
|
||||||
else if (opcode == CMDB_PING)
|
else if (opcode == CMDB_PING)
|
||||||
{
|
{
|
||||||
char msg = (char)CMDR_PING;
|
char msg = (char)CMDR_PING;
|
||||||
_delay_ms(2);
|
_delay_ms(2);
|
||||||
sfbus_send_frame(0xFFFF, &msg, 1);
|
sfbus_send_frame_v2(0xFFFF, &msg, 1);
|
||||||
}
|
}
|
||||||
else if (opcode == CMDB_RPWROFF)
|
else if (opcode == CMDB_RPWROFF)
|
||||||
{
|
{
|
||||||
@@ -163,7 +164,7 @@ void readCommand()
|
|||||||
// invalid opcode
|
// invalid opcode
|
||||||
char msg = CMDR_ERR_INVALID;
|
char msg = CMDR_ERR_INVALID;
|
||||||
_delay_ms(2);
|
_delay_ms(2);
|
||||||
sfbus_send_frame(0xFFFF, &msg, 1);
|
sfbus_send_frame_v2(0xFFFF, &msg, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(payload);
|
free(payload);
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ uint8_t sts_flag_busy = 0; // device is busy
|
|||||||
uint16_t currentVoltage = 0; // current ADC reading
|
uint16_t currentVoltage = 0; // current ADC reading
|
||||||
uint8_t currentFaultReadings = 0; // ticks with faulty readings (too many will
|
uint8_t currentFaultReadings = 0; // ticks with faulty readings (too many will
|
||||||
// trip pwrdwn and sts_flag_fuse)
|
// trip pwrdwn and sts_flag_fuse)
|
||||||
|
uint16_t timer_ticks = 0;
|
||||||
|
|
||||||
int STEPS_OFFSET = 0;
|
int STEPS_OFFSET = 0;
|
||||||
// initialize motor controller
|
// initialize motor controller
|
||||||
@@ -109,6 +110,7 @@ void readVoltage()
|
|||||||
// MAIN service routine. Called by timer 1
|
// MAIN service routine. Called by timer 1
|
||||||
ISR(TIMER1_COMPA_vect)
|
ISR(TIMER1_COMPA_vect)
|
||||||
{
|
{
|
||||||
|
timer_ticks ++;
|
||||||
readVoltage(); // read and check voltage
|
readVoltage(); // read and check voltage
|
||||||
if (sts_flag_pwrdwn == 1 || sts_flag_failsafe == 1)
|
if (sts_flag_pwrdwn == 1 || sts_flag_failsafe == 1)
|
||||||
{
|
{
|
||||||
@@ -239,7 +241,7 @@ uint8_t getSts()
|
|||||||
status |= sts_flag_fuse << 2; // bit 2: fuse blown
|
status |= sts_flag_fuse << 2; // bit 2: fuse blown
|
||||||
status |= sts_flag_pwrdwn << 4; // bit 4: device powered down
|
status |= sts_flag_pwrdwn << 4; // bit 4: device powered down
|
||||||
status |= sts_flag_failsafe << 5; // bit 5: failsafe active
|
status |= sts_flag_failsafe << 5; // bit 5: failsafe active
|
||||||
status |= sts_flag_busy << 6; // bit 6: failsafe active
|
status |= sts_flag_busy << 6; // bit 6: device busy
|
||||||
if ((PIND & (1 << PD3)) == 0)
|
if ((PIND & (1 << PD3)) == 0)
|
||||||
{
|
{
|
||||||
status |= (1 << 3);
|
status |= (1 << 3);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ uint8_t getSts();
|
|||||||
uint16_t getVoltage();
|
uint16_t getVoltage();
|
||||||
void mctrl_power(uint8_t state);
|
void mctrl_power(uint8_t state);
|
||||||
|
|
||||||
|
uint16_t timer_ticks;
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
* https://github.com/dennis9819/splitflap_v1
|
* https://github.com/dennis9819/splitflap_v1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "mctrl.h"
|
||||||
#include "rs485.h"
|
#include "rs485.h"
|
||||||
|
|
||||||
void rs485_init()
|
void rs485_init()
|
||||||
@@ -21,14 +22,7 @@ void rs485_init()
|
|||||||
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // 8bit data format
|
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // 8bit data format
|
||||||
}
|
}
|
||||||
|
|
||||||
void dbg(char data)
|
// send byte over rs485
|
||||||
{
|
|
||||||
while (!(UCSRA & (1 << UDRE)))
|
|
||||||
;
|
|
||||||
UDR = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void rs485_send_c(char data)
|
void rs485_send_c(char data)
|
||||||
{
|
{
|
||||||
PORTD |= (1 << PD2); // set transciever to transmitt
|
PORTD |= (1 << PD2); // set transciever to transmitt
|
||||||
@@ -39,17 +33,10 @@ void rs485_send_c(char data)
|
|||||||
while (!(UCSRA & (1 << TXC)))
|
while (!(UCSRA & (1 << TXC)))
|
||||||
{
|
{
|
||||||
}; // wait until transmitt complete
|
}; // wait until transmitt complete
|
||||||
PORTD &= ~(1 << PD2); // set transciever to transmitt
|
PORTD &= ~(1 << PD2); // set transciever back to receive
|
||||||
}
|
|
||||||
|
|
||||||
void rs485_send_str(char *data)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < sizeof(data); i++)
|
|
||||||
{
|
|
||||||
rs485_send_c(data[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// receive without timeout
|
||||||
char rs485_recv_c()
|
char rs485_recv_c()
|
||||||
{
|
{
|
||||||
while (!(UCSRA & (1 << RXC)))
|
while (!(UCSRA & (1 << RXC)))
|
||||||
@@ -57,42 +44,69 @@ char rs485_recv_c()
|
|||||||
return UDR;
|
return UDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SFBUS Functions
|
// receive with timeout
|
||||||
uint8_t sfbus_recv_frame(uint16_t address, char *payload)
|
int rs485_recv_c_rxout(uint8_t timeout, char *data)
|
||||||
{
|
{
|
||||||
while (rs485_recv_c() != SFBUS_SOF_BYTE)
|
timer_ticks = 0;
|
||||||
|
while (!(UCSRA & (1 << RXC)))
|
||||||
{
|
{
|
||||||
} // Wwait for start byte
|
if (timer_ticks > timeout)
|
||||||
|
{
|
||||||
uint8_t frm_version = rs485_recv_c();
|
return 0;
|
||||||
if (frm_version != 0)
|
}
|
||||||
return 0;
|
|
||||||
uint8_t frm_length = rs485_recv_c();
|
|
||||||
uint8_t frm_addrL = rs485_recv_c();
|
|
||||||
uint8_t frm_addrH = rs485_recv_c();
|
|
||||||
|
|
||||||
uint16_t frm_addr = frm_addrL | (frm_addrH << SHIFT_1B);
|
|
||||||
if (frm_addr != address)
|
|
||||||
return 0;
|
|
||||||
char *_payload = payload;
|
|
||||||
for (uint8_t i = 0; i < (frm_length - 3); i++)
|
|
||||||
{
|
|
||||||
*_payload = rs485_recv_c();
|
|
||||||
_payload++;
|
|
||||||
}
|
}
|
||||||
|
*data = UDR;
|
||||||
if (rs485_recv_c() != SFBUS_EOF_BYTE)
|
return 1;
|
||||||
return -1;
|
|
||||||
return frm_length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfbus_send_frame(uint16_t address, char *payload, uint8_t length)
|
// SFBUS Functions
|
||||||
|
// receive paket with crc checking and timeout
|
||||||
|
uint8_t sfbus_recv_frame_v2(uint16_t address, char *payload)
|
||||||
|
{
|
||||||
|
const uint8_t RX_TIMEOUT = 2;
|
||||||
|
while (rs485_recv_c() != SFBUS_SOF_BYTE)
|
||||||
|
{
|
||||||
|
} // Wait for start byte
|
||||||
|
uint8_t frm_version, frm_length;
|
||||||
|
if (rs485_recv_c_rxout(RX_TIMEOUT, (char *)&frm_version) == 0) // read header: version
|
||||||
|
return -1;
|
||||||
|
if (rs485_recv_c_rxout(RX_TIMEOUT, (char *)&frm_length) == 0) // read header: payload length
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// ALWAYS!!! receive full packet to avoid sync error
|
||||||
|
for (int i = 0; i < frm_length; i++)
|
||||||
|
{
|
||||||
|
if (rs485_recv_c_rxout(RX_TIMEOUT, payload + i) == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check protocol version
|
||||||
|
if (frm_version != 0x01)
|
||||||
|
{
|
||||||
|
return -1; // abort on incompatible version
|
||||||
|
}
|
||||||
|
// if version matches, read address and checksum
|
||||||
|
uint16_t recv_addr = (*(payload + 0) & 0xFF) | ((*(payload + 1) & 0xFF) << SHIFT_1B);
|
||||||
|
uint16_t checksum = (*(payload + (frm_length - 2)) & 0xFF) | ((*(payload + (frm_length - 1)) & 0xFF) << SHIFT_1B);
|
||||||
|
|
||||||
|
// calculate checksum of received payload
|
||||||
|
uint16_t checksum_calc = calc_CRC16(payload + 2, frm_length - 4);
|
||||||
|
|
||||||
|
// return length on valid address and crc, return 0 to ignore
|
||||||
|
return (checksum == checksum_calc && address == recv_addr) ? frm_length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send paket with crc
|
||||||
|
void sfbus_send_frame_v2(uint16_t address, char *payload, uint8_t length)
|
||||||
{
|
{
|
||||||
uint8_t framelen = length;
|
uint8_t framelen = length;
|
||||||
|
// claculate crc value
|
||||||
|
uint16_t crc = calc_CRC16(payload, framelen);
|
||||||
|
|
||||||
rs485_send_c(SFBUS_SOF_BYTE); // send startbyte 3 times
|
rs485_send_c(SFBUS_SOF_BYTE); // send startbyte
|
||||||
rs485_send_c(0); // send protocol version
|
rs485_send_c(1); // send protocol version
|
||||||
rs485_send_c((char)(framelen + 3)); // send lentgh of remaining frame
|
rs485_send_c((char)(framelen + 4)); // send lentgh of remaining frame
|
||||||
|
|
||||||
rs485_send_c((char)(address & 0xFF)); // target address
|
rs485_send_c((char)(address & 0xFF)); // target address
|
||||||
rs485_send_c((char)((address >> SHIFT_1B) & 0xFF));
|
rs485_send_c((char)((address >> SHIFT_1B) & 0xFF));
|
||||||
@@ -104,5 +118,32 @@ void sfbus_send_frame(uint16_t address, char *payload, uint8_t length)
|
|||||||
framelen--;
|
framelen--;
|
||||||
}
|
}
|
||||||
|
|
||||||
rs485_send_c(SFBUS_EOF_BYTE); // send end of frame byte
|
rs485_send_c((char)(crc & 0xFF)); // send crc
|
||||||
|
rs485_send_c((char)((crc >> SHIFT_1B) & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate crc checksum
|
||||||
|
uint16_t calc_CRC16(char *buffer, uint8_t len)
|
||||||
|
{
|
||||||
|
uint16_t crc16 = 0xFFFF;
|
||||||
|
for (uint8_t pos = 0; pos < len; pos++)
|
||||||
|
{
|
||||||
|
char byte_value = *(buffer); // read byte after byte from buffer
|
||||||
|
buffer++;
|
||||||
|
|
||||||
|
crc16 ^= byte_value; // XOR byte into least sig. byte of crc
|
||||||
|
for (int i = 8; i != 0; i--)
|
||||||
|
{ // Loop over each bit
|
||||||
|
if ((crc16 & 0x0001) != 0)
|
||||||
|
{ // If the LSB is set
|
||||||
|
crc16 >>= 1; // Shift right and XOR 0xA001
|
||||||
|
crc16 ^= 0xA001;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Else LSB is not set
|
||||||
|
crc16 >>= 1; // Just shift right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc16;
|
||||||
}
|
}
|
||||||
@@ -9,24 +9,29 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
//#define F_CPU 16000000UL
|
//#define F_CPU 16000000UL
|
||||||
#define UART_BAUD 19200 // RS485 baud rate
|
//#define UART_BAUD 19200 // RS485 baud rate
|
||||||
#define BAUDRATE ((F_CPU) / (UART_BAUD * 16UL) - 1) // set baud rate value for UBRR
|
#define UART_BAUD 57600 // RS485 baud rate
|
||||||
|
#define BAUDRATE ((F_CPU) / (UART_BAUD * 16UL) - 1) // set baud rate value for UBRR
|
||||||
|
|
||||||
#define SFBUS_SOF_BYTE '+' // Byte marks start of frame
|
#define SFBUS_SOF_BYTE '+' // Byte marks start of frame
|
||||||
#define SFBUS_EOF_BYTE '$' // Byte marks end of frame
|
#define SFBUS_EOF_BYTE '$' // Byte marks end of frame
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
void dbg(char data);
|
|
||||||
|
|
||||||
void rs485_init(void);
|
void rs485_init(void);
|
||||||
void rs485_send_c(char data);
|
void rs485_send_c(char data);
|
||||||
void rs485_send_str(char* data);
|
char rs485_recv_c(void);
|
||||||
char rs485_recv_c(void);
|
int rs485_recv_c_rxout(uint8_t timeout, char *data);
|
||||||
|
|
||||||
uint8_t sfbus_recv_frame(uint16_t address, char* payload);
|
uint8_t sfbus_recv_frame_v2(uint16_t address, char *payload);
|
||||||
void sfbus_send_frame(uint16_t address, char* payload, uint8_t length);
|
void sfbus_send_frame_v2(uint16_t address, char *payload, uint8_t length);
|
||||||
|
uint16_t calc_CRC16(char *buffer, uint8_t len);
|
||||||
|
|
||||||
|
// auxilary var for uart timeout
|
||||||
|
extern uint16_t timer_ticks;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,26 +14,12 @@ After the transmission of the payload length, the receiver *node* counts the rem
|
|||||||
|
|
||||||
In protocol version 1.0, the receiving *node* expects the last byte to be `0x24`. If this is not the case, the transmission is marked as invalid and will not be processed further. The receiving *node* will not send any response.
|
In protocol version 1.0, the receiving *node* expects the last byte to be `0x24`. If this is not the case, the transmission is marked as invalid and will not be processed further. The receiving *node* will not send any response.
|
||||||
|
|
||||||
In protocol version 2.0, the checksum is verified. If it does not match the payload, the transmission is marked as invalid and will not be processed further. The receiving *node* will not send any response.
|
In protocol version 2.0, the checksum of the payload is verified. If it does not match the payload, the transmission is marked as invalid and will not be processed further. The receiving *node* will not send any response.
|
||||||
No stop-byte is expected. Version 2.0 also requires a timeout-check in the receiving function. This allows the bus to support hot-plugging, to cancel incomplete or invalid packages and reliably detect the start of a new transmission.
|
No stop-byte is expected. Version 2.0 also requires a timeout-check in the receiving function. This allows the bus to support hot-plugging, to cancel incomplete or invalid packages and reliably detect the start of a new transmission.
|
||||||
|
|
||||||
The communication is typically unidirectional. Lost transmissions are not detectable. The *flap controller* NEVER initiates a communication to the *main controller interface*. *node* to *master* communication only occures in response to specific commands. This is specified in the command / payload documentation.
|
The communication is typically unidirectional. Lost transmissions are not detectable. The *flap controller* NEVER initiates a communication to the *main controller interface*. *node* to *master* communication only occures in response to specific commands. This is specified in the command / payload documentation.
|
||||||
|
|
||||||
## Packet format (1.0)
|
|
||||||
```
|
|
||||||
+---------------------------------+----------------------------------------+
|
|
||||||
| Header | Frame |
|
|
||||||
+------------+-----------+--------+----------+-----------------+-----------+
|
|
||||||
| Start-Byte | Protocol- | Frame- | Receiver | Payload | Stop-Byte |
|
|
||||||
| | Version | Length | Address | | |
|
|
||||||
| 0x2B | 0x00 | 1 byte | 2 bytes | framelemgth - 3 | 0x24 |
|
|
||||||
+------------+-----------+--------+----------+-----------------+-----------+
|
|
||||||
The frame length includes the address and stop-byte
|
|
||||||
Therefor, the payload is framelegth - 3.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Packet format (2.0)
|
## Packet format (2.0)
|
||||||
*This is not yet implemented!!*
|
|
||||||
```
|
```
|
||||||
+---------------------------------+----------------------------------------+
|
+---------------------------------+----------------------------------------+
|
||||||
| Header | Frame |
|
| Header | Frame |
|
||||||
@@ -46,6 +32,7 @@ The communication is typically unidirectional. Lost transmissions are not detect
|
|||||||
Therefor, the payload is framelegth - 4.
|
Therefor, the payload is framelegth - 4.
|
||||||
|
|
||||||
Checksum is based on MODBUS CRC algorithm. Check implementation in sfbus.c
|
Checksum is based on MODBUS CRC algorithm. Check implementation in sfbus.c
|
||||||
|
Checksum is only created for the payload, not the entire frame or packet.
|
||||||
```
|
```
|
||||||
|
|
||||||
More infromation regarding the crc algorithm: https://ctlsys.com/support/how_to_compute_the_modbus_rtu_message_crc/
|
More infromation regarding the crc algorithm: https://ctlsys.com/support/how_to_compute_the_modbus_rtu_message_crc/
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ JSON_C_DIR=/path/to/json_c/install
|
|||||||
CFLAGS += -I$(JSON_C_DIR)/include/json-c
|
CFLAGS += -I$(JSON_C_DIR)/include/json-c
|
||||||
# Or to use lines like: #include <json-c/json_object.h>
|
# Or to use lines like: #include <json-c/json_object.h>
|
||||||
#CFLAGS += -I$(JSON_C_DIR)/include
|
#CFLAGS += -I$(JSON_C_DIR)/include
|
||||||
LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c
|
LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c # json-c lib
|
||||||
LDFLAGS+= -L$(JSON_C_DIR)/lib -lws
|
LDFLAGS+= -L$(JSON_C_DIR)/lib -lws # websockets lib
|
||||||
CPPFLAGS ?= $(INC_FLAGS) -MMD -MP
|
CPPFLAGS ?= $(INC_FLAGS) -MMD -MP
|
||||||
|
|
||||||
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
|
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
|
||||||
const char *device_config_file = "./flapconfig.json";
|
char *device_config_file = "./flapconfig.json";
|
||||||
int fd;
|
int fd;
|
||||||
// command handlers
|
// command handlers
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ void cmd_dm_print(json_object *req, json_object *res)
|
|||||||
{
|
{
|
||||||
int x = json_object_get_int(jx);
|
int x = json_object_get_int(jx);
|
||||||
int y = json_object_get_int(jy);
|
int y = json_object_get_int(jy);
|
||||||
char *str = json_object_get_string(jstr);
|
const char *str = json_object_get_string(jstr);
|
||||||
devicemgr_printText(str, x, y);
|
devicemgr_printText(str, x, y);
|
||||||
json_object_object_add(res, "ack", json_object_new_boolean(true));
|
json_object_object_add(res, "ack", json_object_new_boolean(true));
|
||||||
}
|
}
|
||||||
@@ -332,7 +332,7 @@ json_object *parse_command(json_object *req)
|
|||||||
json_object *commandObj;
|
json_object *commandObj;
|
||||||
json_object *res = json_object_new_object();
|
json_object *res = json_object_new_object();
|
||||||
json_object_object_get_ex(req, "command", &commandObj);
|
json_object_object_get_ex(req, "command", &commandObj);
|
||||||
char *command = json_object_get_string(commandObj);
|
const char *command = json_object_get_string(commandObj);
|
||||||
free(commandObj);
|
free(commandObj);
|
||||||
// command 'table'
|
// command 'table'
|
||||||
if (strcmp(command, "dm_dump") == 0)
|
if (strcmp(command, "dm_dump") == 0)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "devicemgr.h"
|
#include "devicemgr.h"
|
||||||
#include <json-c/json_object.h>
|
#include <json-c/json_object.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
enum SFDEVICE_STATE
|
enum SFDEVICE_STATE
|
||||||
{
|
{
|
||||||
@@ -29,6 +30,7 @@ enum SFDEVICE_POWER
|
|||||||
UNKNOWN
|
UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct SFDEVICE
|
struct SFDEVICE
|
||||||
{
|
{
|
||||||
int pos_x;
|
int pos_x;
|
||||||
@@ -262,7 +264,7 @@ void setSingleRaw(int id, int flap)
|
|||||||
devices[nextFreeSlot].current_flap = flap;
|
devices[nextFreeSlot].current_flap = flap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void devicemgr_printText(char *text, int x, int y)
|
void devicemgr_printText(const char *text, int x, int y)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < strlen(text); i++)
|
for (int i = 0; i < strlen(text); i++)
|
||||||
{
|
{
|
||||||
@@ -340,7 +342,7 @@ int devicemgr_remove(int id)
|
|||||||
{
|
{
|
||||||
devices[nextFreeSlot].deviceState = REMOVED;
|
devices[nextFreeSlot].deviceState = REMOVED;
|
||||||
devices[nextFreeSlot].address = 0;
|
devices[nextFreeSlot].address = 0;
|
||||||
devices[nextFreeSlot].rs485_descriptor = NULL;
|
devices[nextFreeSlot].rs485_descriptor = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +363,7 @@ int devicemgr_save(char *file)
|
|||||||
|
|
||||||
json_object_object_add(root, "devices", device_array);
|
json_object_object_add(root, "devices", device_array);
|
||||||
|
|
||||||
char *data = json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY);
|
const char *data = json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY);
|
||||||
printf("[INFO][console] store data to %s\n", file);
|
printf("[INFO][console] store data to %s\n", file);
|
||||||
|
|
||||||
FILE *fptr;
|
FILE *fptr;
|
||||||
@@ -373,7 +375,7 @@ int devicemgr_save(char *file)
|
|||||||
int devicemgr_load(char *file)
|
int devicemgr_load(char *file)
|
||||||
{
|
{
|
||||||
FILE *fptr;
|
FILE *fptr;
|
||||||
const char *line_in_file = malloc(JSON_MAX_LINE_LEN); // maximum of 256 bytes per line;
|
char *line_in_file = malloc(JSON_MAX_LINE_LEN); // maximum of 256 bytes per line;
|
||||||
fptr = fopen(file, "r");
|
fptr = fopen(file, "r");
|
||||||
json_tokener *tok = json_tokener_new();
|
json_tokener *tok = json_tokener_new();
|
||||||
json_object *jobj = NULL;
|
json_object *jobj = NULL;
|
||||||
@@ -382,7 +384,7 @@ int devicemgr_load(char *file)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int read_ret = fgets(line_in_file, JSON_MAX_LINE_LEN, fptr); // read line from file
|
char* read_ret = fgets(line_in_file, JSON_MAX_LINE_LEN, fptr); // read line from file
|
||||||
stringlen = strlen(line_in_file);
|
stringlen = strlen(line_in_file);
|
||||||
// printf("Read line with chars: %i : %s", stringlen, line_in_file); // only for testing
|
// printf("Read line with chars: %i : %s", stringlen, line_in_file); // only for testing
|
||||||
jobj = json_tokener_parse_ex(tok, line_in_file, stringlen);
|
jobj = json_tokener_parse_ex(tok, line_in_file, stringlen);
|
||||||
|
|||||||
@@ -31,5 +31,8 @@ void devicemgr_init();
|
|||||||
int devicemgr_print(char *text);
|
int devicemgr_print(char *text);
|
||||||
int devicemgr_refresh();
|
int devicemgr_refresh();
|
||||||
int devicemgr_save(char *file);
|
int devicemgr_save(char *file);
|
||||||
void devicemgr_printText(char *text, int x, int y);
|
void devicemgr_printText(const char *text, int x, int y);
|
||||||
void devicemgr_printFlap(int flap, int x, int y);
|
void devicemgr_printFlap(int flap, int x, int y);
|
||||||
|
int devicemgr_load(char *file);
|
||||||
|
int devicemgr_load_single(json_object *device_obj);
|
||||||
|
int devicemgr_remove(int id);
|
||||||
@@ -3,14 +3,7 @@
|
|||||||
* Copyright (c) 2024-2025 GuniaLabs (www.dennisgunia.de)
|
* Copyright (c) 2024-2025 GuniaLabs (www.dennisgunia.de)
|
||||||
* Authors: Dennis Gunia
|
* Authors: Dennis Gunia
|
||||||
*
|
*
|
||||||
* This program is free software (...)
|
* This program is licenced under AGPL-3.0 license.
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program (...)
|
|
||||||
*
|
|
||||||
* You can be released from the requirements of the license by purchasing
|
|
||||||
* a commercial license. Buying such a license is mandatory as soon as you
|
|
||||||
* develop commercial activities involving the split-flap software without
|
|
||||||
* disclosing the source code of your own applications (...)
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -28,6 +21,7 @@
|
|||||||
#include "ftdi485.h"
|
#include "ftdi485.h"
|
||||||
#include "sfbus.h"
|
#include "sfbus.h"
|
||||||
|
|
||||||
|
extern char *optarg;
|
||||||
|
|
||||||
void printUsage(char *argv[])
|
void printUsage(char *argv[])
|
||||||
{
|
{
|
||||||
@@ -86,7 +80,7 @@ int main(int argc, char *argv[])
|
|||||||
setvbuf(stdout, NULL, _IONBF, 0); // do not buffer stdout!!!!
|
setvbuf(stdout, NULL, _IONBF, 0); // do not buffer stdout!!!!
|
||||||
|
|
||||||
printf("Open device at %s\n", port);
|
printf("Open device at %s\n", port);
|
||||||
int fd = rs485_init(port, B19200); // setup rs485
|
int fd = rs485_init(port, B57600); // setup rs485
|
||||||
|
|
||||||
if (strcmp(command, "ping") == 0)
|
if (strcmp(command, "ping") == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ void print_bufferHexRx(char *buffer, int length, u_int16_t address)
|
|||||||
{
|
{
|
||||||
printf("Rx (0x%04X): ", address);
|
printf("Rx (0x%04X): ", address);
|
||||||
print_charHex(buffer, length);
|
print_charHex(buffer, length);
|
||||||
printf(" | %i bytes received\n", length);
|
printf("| %i bytes received\n", length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_bufferHexTx(char *buffer, int length, u_int16_t address)
|
void print_bufferHexTx(char *buffer, int length, u_int16_t address)
|
||||||
{
|
{
|
||||||
printf("Tx (0x%04X): ", address);
|
printf("Tx (0x%04X): ", address);
|
||||||
print_charHex(buffer, length);
|
print_charHex(buffer, length);
|
||||||
printf(" | %i bytes sent\n", length);
|
printf("| %i bytes sent\n", length);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer)
|
ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer)
|
||||||
@@ -43,7 +43,7 @@ ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer)
|
|||||||
int retryCount = 2;
|
int retryCount = 2;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
len = sfbus_recv_frame(fd, address, buffer);
|
len = sfbus_recv_frame_v2(fd, address, buffer);
|
||||||
retryCount--;
|
retryCount--;
|
||||||
if (retryCount == 0)
|
if (retryCount == 0)
|
||||||
{
|
{
|
||||||
@@ -51,12 +51,14 @@ ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} while (len <= 0);
|
} while (len <= 0);
|
||||||
print_bufferHexRx(buffer, len - 3, address);
|
print_bufferHexRx(buffer, len - 4, address);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sfbus_recv_frame(int fd, u_int16_t address, char *buffer)
|
ssize_t sfbus_recv_frame_v2(int fd, u_int16_t address, char *buffer)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
// wait for start byte
|
// wait for start byte
|
||||||
char byte = 0x00;
|
char byte = 0x00;
|
||||||
int retryCount = 3;
|
int retryCount = 3;
|
||||||
@@ -71,10 +73,9 @@ ssize_t sfbus_recv_frame(int fd, u_int16_t address, char *buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
u_int8_t frm_version;
|
u_int8_t frm_version;
|
||||||
u_int8_t frm_addr_l;
|
u_int8_t frm_addr_l, frm_addr_h;
|
||||||
u_int8_t frm_addr_h;
|
|
||||||
u_int8_t frm_length;
|
u_int8_t frm_length;
|
||||||
u_int8_t frm_eof;
|
u_int8_t frm_crc_l, frm_crc_h;
|
||||||
|
|
||||||
read(fd, &frm_version, 1);
|
read(fd, &frm_version, 1);
|
||||||
read(fd, &frm_length, 1);
|
read(fd, &frm_length, 1);
|
||||||
@@ -84,60 +85,32 @@ ssize_t sfbus_recv_frame(int fd, u_int16_t address, char *buffer)
|
|||||||
u_int16_t dst_addr = frm_addr_l | (frm_addr_h << 8);
|
u_int16_t dst_addr = frm_addr_l | (frm_addr_h << 8);
|
||||||
if (dst_addr != address)
|
if (dst_addr != address)
|
||||||
{
|
{
|
||||||
return 0;
|
//return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int8_t frm_length_counter = frm_length - 3;
|
|
||||||
// read all bytes:
|
// read all bytes:
|
||||||
while (frm_length_counter > 0)
|
read(fd, buffer, frm_length - 4); // read n bytes from buffer where n = payload length
|
||||||
{
|
// read crc
|
||||||
read(fd, buffer, 1);
|
u_int16_t frm_crc = 0xFFFF; // read crc value
|
||||||
buffer++;
|
read(fd, &frm_crc, 2);
|
||||||
frm_length_counter--;
|
|
||||||
}
|
|
||||||
read(fd, &frm_eof, 1);
|
|
||||||
|
|
||||||
if (frm_eof == '$')
|
u_int16_t calc_crc = calc_CRC16(buffer, frm_length - 4); // calculate CRC
|
||||||
|
|
||||||
|
|
||||||
|
if (frm_crc == calc_crc)
|
||||||
{
|
{
|
||||||
|
printf("crc check okay! expected: %04X received: %04X\n", calc_crc, frm_crc);
|
||||||
return frm_length;
|
return frm_length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
print_bufferHexRx(buffer, frm_length - 4, address);
|
||||||
|
printf("crc check failed! expected: %04X received: %04X\n", calc_crc, frm_crc);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfbus_send_frame(int fd, u_int16_t address, u_int8_t length, char *buffer)
|
|
||||||
{
|
|
||||||
int frame_size_complete = length + 6;
|
|
||||||
char *frame = malloc(frame_size_complete);
|
|
||||||
char *frame_ptr = frame;
|
|
||||||
|
|
||||||
*frame = '+'; // startbyte
|
|
||||||
frame++;
|
|
||||||
*frame = 0; // protocol version
|
|
||||||
frame++;
|
|
||||||
*frame = length + 3; // length
|
|
||||||
frame++;
|
|
||||||
*frame = (address);
|
|
||||||
frame++;
|
|
||||||
*frame = ((address >> 8));
|
|
||||||
frame++;
|
|
||||||
while (length > 0)
|
|
||||||
{
|
|
||||||
*frame = *buffer;
|
|
||||||
length--;
|
|
||||||
buffer++;
|
|
||||||
frame++;
|
|
||||||
}
|
|
||||||
*frame = '$'; // startbyte
|
|
||||||
|
|
||||||
int result = write(fd, frame_ptr, frame_size_complete);
|
|
||||||
print_bufferHexTx(frame_ptr + 5, frame_size_complete - 6, address);
|
|
||||||
free(frame_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send SFBus frame with protocol version 2.0 and calculated CRC
|
* Send SFBus frame with protocol version 2.0 and calculated CRC
|
||||||
*/
|
*/
|
||||||
@@ -157,9 +130,8 @@ void sfbus_send_frame_v2(int fd, u_int16_t address, u_int8_t length, char *buffe
|
|||||||
|
|
||||||
// add crc to end of frame
|
// add crc to end of frame
|
||||||
u_int16_t crc = calc_CRC16(buffer, length); // calculate CRC
|
u_int16_t crc = calc_CRC16(buffer, length); // calculate CRC
|
||||||
*(frame + (frame_size_complete - 1)) = (crc); // address high byte
|
*(frame + (frame_size_complete - 2)) = (crc); // address high byte
|
||||||
*(frame + (frame_size_complete - 0)) = ((crc >> 8)); // address low byte
|
*(frame + (frame_size_complete - 1)) = ((crc >> 8)); // address low byte
|
||||||
|
|
||||||
// send data
|
// send data
|
||||||
int result = write(fd, frame, frame_size_complete);
|
int result = write(fd, frame, frame_size_complete);
|
||||||
print_bufferHexTx(frame, frame_size_complete, address);
|
print_bufferHexTx(frame, frame_size_complete, address);
|
||||||
@@ -194,9 +166,9 @@ int sfbus_read_eeprom(int fd, u_int16_t address, char *buffer)
|
|||||||
{
|
{
|
||||||
char *cmd = "\xF0";
|
char *cmd = "\xF0";
|
||||||
char *_buffer = malloc(256);
|
char *_buffer = malloc(256);
|
||||||
sfbus_send_frame(fd, address, strlen(cmd), cmd);
|
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
|
||||||
int len = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
|
int len = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
|
||||||
if (len != 9)
|
if (len != 10)
|
||||||
{
|
{
|
||||||
printf("Invalid data!\n");
|
printf("Invalid data!\n");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -217,12 +189,12 @@ int sfbus_write_eeprom(int fd, u_int16_t address, char *wbuffer, char *rbuffer)
|
|||||||
char *cmd = malloc(5);
|
char *cmd = malloc(5);
|
||||||
*cmd = (char)0xF1; // write eeprom command
|
*cmd = (char)0xF1; // write eeprom command
|
||||||
memcpy(cmd + 1, wbuffer, 4);
|
memcpy(cmd + 1, wbuffer, 4);
|
||||||
sfbus_send_frame(fd, address, 5, cmd);
|
sfbus_send_frame_v2(fd, address, 5, cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
// wait for readback
|
// wait for readback
|
||||||
char *_buffer = malloc(256);
|
char *_buffer = malloc(256);
|
||||||
int len = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
|
int len = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
|
||||||
if (len != 9)
|
if (len != 10)
|
||||||
{
|
{
|
||||||
printf("Invalid data!\n");
|
printf("Invalid data!\n");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -243,7 +215,7 @@ int sfbus_display(int fd, u_int16_t address, u_int8_t flap)
|
|||||||
char *cmd = malloc(5);
|
char *cmd = malloc(5);
|
||||||
*cmd = (char)0x10; // write eeprom command
|
*cmd = (char)0x10; // write eeprom command
|
||||||
*(cmd + 1) = flap;
|
*(cmd + 1) = flap;
|
||||||
sfbus_send_frame(fd, address, 2, cmd);
|
sfbus_send_frame_v2(fd, address, 2, cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -253,7 +225,7 @@ int sfbus_display_full(int fd, u_int16_t address, u_int8_t flap)
|
|||||||
char *cmd = malloc(5);
|
char *cmd = malloc(5);
|
||||||
*cmd = (char)0x11; // write eeprom command
|
*cmd = (char)0x11; // write eeprom command
|
||||||
*(cmd + 1) = flap;
|
*(cmd + 1) = flap;
|
||||||
sfbus_send_frame(fd, address, 2, cmd);
|
sfbus_send_frame_v2(fd, address, 2, cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -262,7 +234,7 @@ u_int8_t sfbus_read_status(int fd, u_int16_t address, double *voltage, u_int32_t
|
|||||||
{
|
{
|
||||||
char *cmd = "\xF8";
|
char *cmd = "\xF8";
|
||||||
char *_buffer = malloc(256);
|
char *_buffer = malloc(256);
|
||||||
sfbus_send_frame(fd, address, strlen(cmd), cmd);
|
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
|
||||||
int res = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
|
int res = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
@@ -282,7 +254,7 @@ u_int8_t sfbus_read_status(int fd, u_int16_t address, double *voltage, u_int32_t
|
|||||||
void sfbus_reset_device(int fd, u_int16_t address)
|
void sfbus_reset_device(int fd, u_int16_t address)
|
||||||
{
|
{
|
||||||
char *cmd = "\x30";
|
char *cmd = "\x30";
|
||||||
sfbus_send_frame(fd, address, strlen(cmd), cmd);
|
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfbus_motor_power(int fd, u_int16_t address, u_int8_t state)
|
void sfbus_motor_power(int fd, u_int16_t address, u_int8_t state)
|
||||||
@@ -292,7 +264,7 @@ void sfbus_motor_power(int fd, u_int16_t address, u_int8_t state)
|
|||||||
{
|
{
|
||||||
cmd = "\x21";
|
cmd = "\x21";
|
||||||
}
|
}
|
||||||
sfbus_send_frame(fd, address, 1, cmd);
|
sfbus_send_frame_v2(fd, address, 1, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int16_t calc_CRC16(char *buffer, u_int8_t len)
|
u_int16_t calc_CRC16(char *buffer, u_int8_t len)
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
#include "ftdi485.h"
|
#include "ftdi485.h"
|
||||||
|
|
||||||
ssize_t sfbus_recv_frame(int fd, u_int16_t address, char *buffer);
|
ssize_t sfbus_recv_frame_v2(int fd, u_int16_t address, char *buffer);
|
||||||
ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer);
|
ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer);
|
||||||
void sfbus_send_frame(int fd, u_int16_t address, u_int8_t length, char *buffer);
|
void sfbus_send_frame_v2(int fd, u_int16_t address, u_int8_t length, char *buffer);
|
||||||
void print_charHex(char *buffer, int length);
|
void print_charHex(char *buffer, int length);
|
||||||
int sfbus_ping(int fd, u_int16_t address);
|
int sfbus_ping(int fd, u_int16_t address);
|
||||||
int sfbus_read_eeprom(int fd, u_int16_t address, char* buffer);
|
int sfbus_read_eeprom(int fd, u_int16_t address, char* buffer);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ json_object *(*commandparser_func)(json_object *);
|
|||||||
|
|
||||||
// this sections handles ws connections and communications
|
// this sections handles ws connections and communications
|
||||||
// called on opening websocket client
|
// called on opening websocket client
|
||||||
void onopen(ws_cli_conn_t client)
|
void ws_opencon(ws_cli_conn_t client)
|
||||||
{
|
{
|
||||||
char *cli;
|
char *cli;
|
||||||
cli = ws_getaddress(client);
|
cli = ws_getaddress(client);
|
||||||
@@ -26,7 +26,7 @@ void onopen(ws_cli_conn_t client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// called on closing websocket client
|
// called on closing websocket client
|
||||||
void onclose(ws_cli_conn_t client)
|
void ws_closecon(ws_cli_conn_t client)
|
||||||
{
|
{
|
||||||
char *cli;
|
char *cli;
|
||||||
cli = ws_getaddress(client);
|
cli = ws_getaddress(client);
|
||||||
@@ -34,7 +34,7 @@ void onclose(ws_cli_conn_t client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// called on receiving websocket message
|
// called on receiving websocket message
|
||||||
void onmessage(ws_cli_conn_t client, const unsigned char *msg, uint64_t size, int type)
|
void ws_messagehandler(ws_cli_conn_t client, const unsigned char *msg, uint64_t size, int type)
|
||||||
{
|
{
|
||||||
char *cli = ws_getaddress(client);
|
char *cli = ws_getaddress(client);
|
||||||
printf("received message: %s (%zu), from: %s\n", msg, size, cli);
|
printf("received message: %s (%zu), from: %s\n", msg, size, cli);
|
||||||
@@ -55,7 +55,7 @@ void onmessage(ws_cli_conn_t client, const unsigned char *msg, uint64_t size, in
|
|||||||
printf("test");
|
printf("test");
|
||||||
if (commandObj != NULL)
|
if (commandObj != NULL)
|
||||||
{
|
{
|
||||||
char *command = json_object_to_json_string(commandObj);
|
const char *command = json_object_to_json_string(commandObj);
|
||||||
// get key
|
// get key
|
||||||
json_object *res = commandparser_func(req);
|
json_object *res = commandparser_func(req);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
@@ -79,11 +79,11 @@ void onmessage(ws_cli_conn_t client, const unsigned char *msg, uint64_t size, in
|
|||||||
|
|
||||||
void send_json_response(ws_cli_conn_t client, json_object *res)
|
void send_json_response(ws_cli_conn_t client, json_object *res)
|
||||||
{
|
{
|
||||||
char *message = json_object_to_json_string_ext(res, JSON_C_TO_STRING_PRETTY);
|
const char *message = json_object_to_json_string_ext(res, JSON_C_TO_STRING_PRETTY);
|
||||||
ws_sendframe_txt(client, message);
|
ws_sendframe_txt(client, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_json_error(ws_cli_conn_t client, char *error, char *detail)
|
void send_json_error(ws_cli_conn_t client, char *error, const char *detail)
|
||||||
{
|
{
|
||||||
json_object *root = json_object_new_object();
|
json_object *root = json_object_new_object();
|
||||||
json_object_object_add(root, "error", json_object_new_string(error));
|
json_object_object_add(root, "error", json_object_new_string(error));
|
||||||
@@ -105,9 +105,9 @@ int start_webserver(json_object *(*commandparser_func_ptr)(json_object *))
|
|||||||
.port = WS_SERVER_PORT,
|
.port = WS_SERVER_PORT,
|
||||||
.thread_loop = 0,
|
.thread_loop = 0,
|
||||||
.timeout_ms = 1000,
|
.timeout_ms = 1000,
|
||||||
.evs.onopen = &onopen,
|
.evs.onopen = &ws_opencon,
|
||||||
.evs.onclose = &onclose,
|
.evs.onclose = &ws_closecon,
|
||||||
.evs.onmessage = &onmessage});
|
.evs.onmessage = &ws_messagehandler});
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -18,3 +18,10 @@
|
|||||||
#define WS_SERVER_ADDR "localhost"
|
#define WS_SERVER_ADDR "localhost"
|
||||||
|
|
||||||
int start_webserver();
|
int start_webserver();
|
||||||
|
|
||||||
|
void send_json_error(ws_cli_conn_t client, char *error, const char *detail);
|
||||||
|
void send_json_response(ws_cli_conn_t client, json_object *res);
|
||||||
|
|
||||||
|
void ws_messagehandler(ws_cli_conn_t client, const unsigned char *msg, uint64_t size, int type);
|
||||||
|
void ws_opencon(ws_cli_conn_t client);
|
||||||
|
void ws_closecon(ws_cli_conn_t client);
|
||||||
Reference in New Issue
Block a user