/*
* Copyright (C) 2015, 2016 "IoT.bzh"
+ * Copyright (C) 2016 Konsulko Group
* Author "Romain Forlot"
* Author "Jose Bolo"
+ * Author "Scott Murray <scott.murray@konsulko.com>"
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#define _GNU_SOURCE
#include <string.h>
+#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <json-c/json.h>
+#define AFB_BINDING_VERSION 1
#include <afb/afb-binding.h>
-#include <afb/afb-service-itf.h>
-
-// Uncomment this line to pass into can simulation mode
-//#define SIMULATE_HVAC
#define CAN_DEV "vcan0"
struct can_handler {
int socket;
+ bool simulation;
+ char *send_msg;
struct sockaddr_can txAddress;
};
-static struct can_handler can_handler = { .socket = -1 };
+static struct can_handler can_handler = { .socket = -1, .simulation = false, .send_msg = "SENDING CAN FRAME"};
-static int open_can_dev()
+static int open_can_dev_helper()
{
-#if defined(SIMULATE_HVAC)
- DEBUG(interface, "Defining can handler socket to 0 and return");
- can_handler.socket = 0;
- return 0;
-#else
struct ifreq ifr;
- DEBUG(interface, "CAN Handler socket : %d", can_handler.socket);
+ AFB_DEBUG(interface, "CAN Handler socket : %d", can_handler.socket);
close(can_handler.socket);
can_handler.socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (can_handler.socket < 0)
{
- ERROR(interface, "socket could not be created");
+ AFB_ERROR(interface, "socket could not be created");
}
else
{
strcpy(ifr.ifr_name, CAN_DEV);
if(ioctl(can_handler.socket, SIOCGIFINDEX, &ifr) < 0)
{
- ERROR(interface, "ioctl failed");
+ AFB_ERROR(interface, "ioctl failed");
}
else
{
// And bind it to txAddress
if (bind(can_handler.socket, (struct sockaddr *)&can_handler.txAddress, sizeof(can_handler.txAddress)) < 0)
{
- ERROR(interface, "bind failed");
+ AFB_ERROR(interface, "bind failed");
}
else {
return 0;
can_handler.socket = -1;
}
return -1;
-#endif
+}
+
+static int open_can_dev()
+{
+ int rc = retry(open_can_dev_helper);
+ if(rc < 0)
+ {
+ AFB_ERROR(interface, "Open of interface %s failed. Falling back to simulation mode", CAN_DEV);
+ can_handler.socket = 0;
+ can_handler.simulation = true;
+ can_handler.send_msg = "FAKE CAN FRAME";
+ rc = 0;
+ }
+ return rc;
}
// Get original get temperature function from cpp hvacplugin code
static uint8_t to_can_temp(uint8_t value)
{
- int result = ((0xF0 - 0x10) / 15) * value - 16;
+ int result = ((0xF0 - 0x10) / 15) * (value - 15) + 0x10;
if (result < 0x10)
result = 0x10;
if (result > 0xF0)
static uint8_t read_fanspeed()
{
- return hvac_values[3].value ^ 0xFF;
+ return hvac_values[3].value;
}
static int write_can()
txCanFrame.data[6] = 0;
txCanFrame.data[7] = 0;
- DEBUG(interface, "%s: %d %d [%02x %02x %02x %02x %02x %02x %02x %02x]\n",
-#if defined(SIMULATE_HVAC)
- "FAKE CAN FRAME",
-#else
- "SENDING CAN FRAME",
-#endif
+ AFB_DEBUG(interface, "%s: %d %d [%02x %02x %02x %02x %02x %02x %02x %02x]\n",
+ can_handler.send_msg,
txCanFrame.can_id, txCanFrame.can_dlc,
txCanFrame.data[0], txCanFrame.data[1], txCanFrame.data[2], txCanFrame.data[3],
txCanFrame.data[4], txCanFrame.data[5], txCanFrame.data[6], txCanFrame.data[7]);
-#if !defined(SIMULATE_HVAC)
- rc = sendto(can_handler.socket, &txCanFrame, sizeof(struct can_frame), 0,
- (struct sockaddr*)&can_handler.txAddress, sizeof(can_handler.txAddress));
- if (rc < 0)
+ if(!can_handler.simulation)
{
- ERROR(interface, "Sending can frame failed. Attempt to reopen can device socket.");
- retry(open_can_dev);
+ rc = sendto(can_handler.socket, &txCanFrame, sizeof(struct can_frame), 0,
+ (struct sockaddr*)&can_handler.txAddress, sizeof(can_handler.txAddress));
+ if (rc < 0)
+ {
+ AFB_ERROR(interface, "Sending CAN frame failed.");
+ }
}
-#endif
}
else
{
- ERROR(interface, "socket not initialized. Attempt to reopen can device socket.");
- retry(open_can_dev);
+ AFB_ERROR(interface, "socket not initialized. Attempt to reopen can device socket.");
+ open_can_dev();
}
return rc;
}
*/
static void get(struct afb_req request)
{
- DEBUG(interface, "Getting all values");
+ AFB_DEBUG(interface, "Getting all values");
json_object *ret_json;
ret_json = json_object_new_object();
uint8_t saves[sizeof hvac_values / sizeof *hvac_values];
/* records initial values */
- DEBUG(interface, "Records initial values");
+ AFB_DEBUG(interface, "Records initial values");
i = (int)(sizeof hvac_values / sizeof *hvac_values);
while (i) {
i--;
query = afb_req_json(request);
changed = 0;
i = (int)(sizeof hvac_values / sizeof *hvac_values);
- DEBUG(interface, "Looping for args. i: %d", i);
+ AFB_DEBUG(interface, "Looping for args. i: %d", i);
while (i)
{
i--;
- DEBUG(interface, "Searching... query: %s, i: %d, comp: %s", json_object_to_json_string(query), i, hvac_values[i].name);
+ AFB_DEBUG(interface, "Searching... query: %s, i: %d, comp: %s", json_object_to_json_string(query), i, hvac_values[i].name);
if (json_object_object_get_ex(query, hvac_values[i].name, &val))
{
- DEBUG(interface, "We got it. Tests if it is an int or double.");
+ AFB_DEBUG(interface, "We got it. Tests if it is an int or double.");
if (json_object_is_type(val, json_type_int)) {
x = json_object_get_int(val);
- DEBUG(interface, "We get an int: %d",x);
+ AFB_DEBUG(interface, "We get an int: %d",x);
}
else if (json_object_is_type(val, json_type_double)) {
d = json_object_get_double(val);
x = (int)round(d);
- DEBUG(interface, "We get a double: %f => %d",d,x);
+ AFB_DEBUG(interface, "We get a double: %f => %d",d,x);
}
else {
afb_req_fail_f(request, "bad-request",
if (values[i] != x) {
values[i] = (uint8_t)x;
changed = 1;
- DEBUG(interface,"%s changed to %d",hvac_values[i].name,x);
+ AFB_DEBUG(interface,"%s changed to %d",hvac_values[i].name,x);
}
}
else {
- DEBUG(interface, "%s not found in query!",hvac_values[i].name);
+ AFB_DEBUG(interface, "%s not found in query!",hvac_values[i].name);
}
}
/* attemps to set new values */
- DEBUG(interface, "Diff: %d", changed);
+ AFB_DEBUG(interface, "Diff: %d", changed);
if (changed)
{
i = (int)(sizeof hvac_values / sizeof *hvac_values);
int afbBindingV1ServiceInit(struct afb_service service)
{
- return retry(open_can_dev);
+ return open_can_dev();
}