Closed splasky closed 4 years ago
It is not "folder" but "directory." Show the tree view rather than words while you are proposing something.
@splasky Provide the structure you designed here.
TA-endpoint
Written by HY Chang\hychang@biilabs.io\
Create your device folder into devices
.
mkdir devices/<my_device>
impl.c
Makefile
under your device folder.device.h
into your header files.Implement your device operations, which are included from hal/device.h
device.h:
...
#define DECLARE_DEVICE(name) \
void init_##name##_init(void) __attribute__((constructor)); \
void init_##name##_init(void) { name##_device_type.op->init(); }
typedef struct device_type device_t;
enum { DEVICE_OK, DEVICE_ERROR };
struct device_operations {
retcode_t (*init)(void); /**< init for device */
void (*fini)(void); /**< destructor for device */
retcode_t (*get_key)(uint8_t *); /**< get device private key */
retcode_t (*get_device_id)(char *); /**< get device id */
};
struct logging_operations {
void (*write_log)(char *path, char *msg, size_t msg_len);
}; // Will be removed
struct uart_operations {
retcode_t (*init)(const char *device);
void (*write)(const int fd, const char *cmd);
char *(*read)(const int fd);
void (*clean)(const int fd);
};
struct secure_store_operations {
retcode_t (*init)(void); /**< init secure storage */
retcode_t (*write)(const char *name, const uint8_t *bufPtr, size_t bufSize);
retcode_t (*read)(const char *name, uint8_t *bufPtr, size_t *bufSizePtr);
retcode_t (*delete)(const char *name);
};
struct device_type {
const char *name;
int uart_fd;
const struct device_operations *op;
const struct uart_operations *uart;
const struct secure_store_operations *sec_ops;
device_t *next;
};
device_t *get_device(const char *);
retcode_t register_device(struct device_type *dv);
retcode_t unregister_device(struct device_type *dv);
...
add your device into hal/Makefile
:
DEVICES_OBJ = wp7702.o emulator.o device.o mydevice.o
INCLUDES += -I/$(CURDIR)
export DEVICES_OBJ
all: $(DEVICES_OBJ) ... mydevice.o: device.o $(MAKE) -C ../devices/mydevice ...
implement device:
must include
1. impl.c
2. Makefile
edit Makefile, example device name as mydevice:
all: mydevice.o mydevice.o: impl.c $(CC) $(CFLAGS) $(INCLUDES) -c $^ -o $@
`$(CC)`,`$(CFLAGS)`,`$(INCLUDES)` is provide by TA-endpoint. Don't define same flags inside your Makefile.
impl.c
```c=
#include "impl.h"
...
static inline void register_emulator(void);
static inline void unregister_emulator(void);
...
static struct device_operations emulator_ops = {.init = &emulator_init,
.fini = &emulator_release,
.get_key = &emulator_get_key,
.get_device_id = &emulator_get_device_id};
static struct logging_operations emulator_logger = {.write_log = &write_log}; // Will be removed
static struct uart_operations emulator_uart = {
.init = &uart_init, .write = &uart_write, .read = &uart_read, .clean = &uart_clean};
static struct device_type emulator_device_type = {
.name = "emulator", .op = &emulator_ops, .uart = &emulator_uart, .logger = &emulator_logger};
static inline void register_emulator(void) {
int err = register_device(&emulator_device_type);
if (err) LOG_ERROR("register emulator device error:%d", err);
}
static inline void unregister_emulator(void) {
int err = unregister_device(&emulator_device_type);
if (err) LOG_ERROR("unregister device emulator error:%d", err);
}
static int emulator_init(void) {
register_emulator();
return DEVICE_OK;
}
static void emulator_release(void) { unregister_emulator(); }
...
// must be declared at the end of impl.c
DECLARE_DEVICE(emulator);
UML:
classDiagram
class device_operations{
+init(void) int
+get_key(uint8_t*) retcode_t
+get_device_id(char*) retcode_t
+fini(void) void
}
class uart_operations{
+init(const char*) int
+read(const int) char*
+write(const int, const char*) void
+clean(const int) void
}
class secure_store_operations{
+init(void) retcode_t
+write(const char *name, const uint8_t *bufPtr, size_t bufSize) retcode_t
+read(const char *name, uint8_t *bufPtr, size_t *bufSizePtr) retcode_t
+delete(const char *name) retcode_t
}
class device_t{
const char* name
int uart_fd
device_operation* op
uart_operation* uart
device_t* next
}
uart_operations <|-- device_t
device_operations <|-- device_t
secure_store_operations <|-- device_t
class wp7702{
+DECLARE_DEVICE("wp7702")
}
class emulator{
+DECLARE_DEVICE("emulator")
}
device_t <|.. emulator
device_t <|.. wp7702
template inc:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "conn_http.h"
#include "crypto_utils.h"
#include "device.h"
#include "logger.h"
#include "serializer.h"
#include "tryte_byte_conv.h"
#include "tryte_msg.h"
#include "url.h"
#define SSL_SEED "nonce"
#define ADDRESS \
"POWEREDBYTANGLEACCELERATOR999999999999999999999999999999999999999999999999" \
"999999A"
#define ADDR_LEN 81
int runner(const char* host, const char* port, const char* api)
{
uint8_t addr[ADDR_LEN] = ADDRESS, next_addr[ADDR_LEN] = {0}, iv[16] = {0};
char raw_msg[1000] = {0}, ciphertext[1024] = {0};
char tryte_msg[1024] = {0}, msg[1024] = {0};
uint32_t raw_msg_len = 1 + ADDR_LEN + 20, msg_len = 0;
srand(time(NULL));
device_t *dv = get_device("{% device_name %}");
int fd = dv->uart->init("{% uart_port %}");
if (fd < 0) {
LOG_ERROR("Error in initializing UART\n");
return -1;
}
char* log_msg = malloc(sizeof(char)*ADDR_LEN + 3);
memset(log_msg, '0', ADDR_LEN + 3);
snprintf(log_msg, strlen(next_addr), "\n%s", next_addr);
dv->logger->write_log("{% log_path %}", next_addr, strlen(next_addr));
free(log_msg);
char *response = NULL;
time_t timer;
char time_str[26];
struct tm *tm_info;
fd_set rset;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500;
while (true) {
FD_ZERO(&rset);
FD_SET(fd, &rset);
select(fd + 1, &rset, NULL, NULL, &tv);
if (FD_ISSET(fd, &rset)) {
time(&timer);
tm_info = localtime(&timer);
strftime(time_str, 26, "%Y-%m-%d %H:%M:%S", tm_info);
LOG_DEBUG("%s\n", time_str);
gen_rand_trytes(ADDR_LEN, next_addr);
response = dv->uart->read(fd);
snprintf(raw_msg, raw_msg_len, "%s:%s", next_addr, response);
LOG_DEBUG("Raw Message: %s\n", raw_msg);
uint8_t private_key[AES_BLOCK_SIZE] = {0};
uint8_t id[IMSI_LEN] = {0};
if (dv->op->get_key(private_key) != 0) {
LOG_ERROR("%s\n", "get aes key error");
return -1;
}
// fetch Device_ID (IMSI, len <= 16)
if (dv->op->get_device_id(id) != 0) {
LOG_ERROR("%s\n", "get device id error");
return -1;
}
int ciphertext_len = encrypt(raw_msg, strlen(raw_msg), ciphertext, 1024, iv, private_key, id);
if (ciphertext_len == 0) {
LOG_ERROR("encrypt msg error");
return -1;
}
serialize_msg(iv, ciphertext_len, ciphertext, msg, &msg_len);
bytes_to_trytes((const unsigned char *)msg, msg_len, tryte_msg);
// Init http session. verify: check the server CA cert.
char msg_body[1024];
gen_tryte_msg(tryte_msg, addr, msg_body);
if (send_https_msg(host, port, api, msg_body, 1024, SSL_SEED) != HTTP_OK) {
LOG_ERROR("Response from ta server failed");
}
memcpy(addr, next_addr, ADDR_LEN);
free(response);
response = NULL;
LOG_INFO("Finish transaction");
}
dv->uart->clean(fd);
}
}
device will be used:
device_t *dv = get_device("{% device_name %}");
int fd = dv->uart->init("{% uart_port %}");
test_driver.c:
#define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
const char *HOST = STRINGIZE_VALUE_OF(TA_HOST);
const char *PORT = STRINGIZE_VALUE_OF(TA_PORT);
const char *API = STRINGIZE_VALUE_OF(TA_API);
#include "use_models.h"
int main(void) { return runner(HOST, PORT, API); }
build process:
The TA-endpoint is migrated into tangle-accelerator so I close this issue.
There are three directory at the root directory. Why don't we put source code into same
src
directory and put headers file into sameinclude
directory?