diff options
author | Romain Forlot <romain.forlot@iot.bzh> | 2016-11-24 17:41:34 +0100 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2016-11-24 17:41:34 +0100 |
commit | 85f44017fb18205133d369bf16c5d0022984c510 (patch) | |
tree | e450a257b95e9c60defdfbe851edfdfa820c583a /hvac-hybrid-qml-binding.c | |
parent | b20eed56b0d712ea59a5f237eb933787e3fdf45d (diff) |
Convert amb hvac plugin to app framework bindings
Change-Id: I7e67c653c7da219beb645d752fb7afca2c968de5
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'hvac-hybrid-qml-binding.c')
-rw-r--r-- | hvac-hybrid-qml-binding.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/hvac-hybrid-qml-binding.c b/hvac-hybrid-qml-binding.c new file mode 100644 index 0000000..634f12e --- /dev/null +++ b/hvac-hybrid-qml-binding.c @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2015, 2016 "IoT.bzh" + * Author "Manuel Bachmann" + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define _GNU_SOURCE +#include <json-c/json.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <linux/can.h> +#include <string.h> +#include <unistd.h> + +#include <afb/afb-binding.h> + +#define CAN_DEV "can0" + +const struct afb_binding_interface *interface; + +// Initialize CAN payload array that will be sent trough the socket +__u8 can_payload[8] = { + 21, + 21, + 21, + 240, // Don't know why 240 but it was 0xF0 in the original amb hvacplugin + 0, + 1, // Don't know why 1 but it was 0xF0 in the original amb hvacplugin + 0, // Don't know why 0 but it was 0xF0 in the original amb hvacplugin + 0 // Don't know why 0 but it was 0xF0 in the original amb hvacplugin +}; + +struct can_handler{ + int socket; + struct sockaddr_can txAddress; +}; + +struct can_handler *ch; + +/***************************************************************************************/ +/***************************************************************************************/ +/** **/ +/** **/ +/** SECTION: HANDLE CAN DEVICE **/ +/** **/ +/** **/ +/***************************************************************************************/ +/***************************************************************************************/ + +static struct can_handler open_can_dev() +{ + struct can_handler ch; + ch.socket = -1; + + ch.socket = socket(PF_CAN, SOCK_RAW, CAN_RAW); + printf("Socket: %i\n", ch.socket); + if (ch.socket < 0) + { + printf("ERROR: socket could not be created\n"); + } + else + { + struct ifreq ifr; + + // Attemts to open a socket to CAN bus + strcpy(ifr.ifr_name, CAN_DEV); + if(ioctl(ch.socket, SIOCGIFINDEX, &ifr) < 0) + { + close(ch.socket); + ch.socket = -1; + printf("ERROR: ioctl failed\n"); + } + else + { + ch.txAddress.can_family = AF_CAN; + ch.txAddress.can_ifindex = ifr.ifr_ifindex; + + // And bind it to ch.txAddress struct + if (bind(ch.socket, (struct sockaddr *)&ch.txAddress, sizeof(ch.txAddress)) < 0) + { + close(ch.socket); + ch.socket = -1; + printf("ERROR: bind failed\n"); + } + return ch; + } + } + printf("Error: unexpected behavior\n"); + return ch; +} + +static void close_can_dev(struct can_handler ch) +{ + int socketId = ch.socket; + if(socketId >= 0) + { + close(socketId); + printf("Socket closed\n"); + } +} + +static void write_can(struct can_handler ch) +{ + printf("Write to CAN bus\n"); + // Hardcoded can_id and dlc (data lenght code) + struct can_frame txCanFrame; + txCanFrame.can_id = 0x30; + txCanFrame.can_dlc = 8; + + if (ch.socket >= 0) + { + printf("Send CAN message\n"); + + txCanFrame.data[0] = can_payload[0]; + txCanFrame.data[1] = can_payload[1]; + txCanFrame.data[2] = (can_payload[0] + can_payload[1]) & 0x02; + txCanFrame.data[3] = can_payload[3]; + txCanFrame.data[4] = can_payload[4]; + txCanFrame.data[5] = can_payload[5]; + txCanFrame.data[6] = can_payload[6]; + txCanFrame.data[7] = can_payload[7]; + + sendto(ch.socket, &txCanFrame, sizeof(struct can_frame), 0, + (struct sockaddr*)&ch.txAddress, sizeof(ch.txAddress)); + } + else + { + printf("Error: socket not initialized\n"); + } + printf("Error sending on CAN bus. Unexpected behavior"); +} + +static int read_temp_left_zone() +{ + return can_payload[0]; +} + +static int read_temp_right_zone() +{ + return can_payload[1]; +} + +static int read_fanspeed() +{ + return can_payload[4]; +} + +/***************************************************************************************/ +/***************************************************************************************/ +/** **/ +/** **/ +/** SECTION: BINDING VERBS IMPLEMENTATION **/ +/** **/ +/** **/ +/***************************************************************************************/ +/***************************************************************************************/ + +/* + * @brief Simple afb-daemon ping + * + * @param struct afb_req : an afb request structure + * + */ +static void ping (struct afb_req request) +{ + static int pingcount = 0; + + json_object *query = afb_req_json(request); + afb_req_success_f(request, NULL, "Ping Binder Daemon count=%d query=%s", ++pingcount, json_object_to_json_string(query)); +} + +/* + * @brief Get fan speed HVAC system + * + * @param struct afb_req : an afb request structure + * + */ +static void get_fanspeed(struct afb_req request) +{ + json_object *ret_json; + int fanspeed = read_fanspeed(); + + ret_json = json_object_new_object(); + json_object_object_add(ret_json, "FanSpeed", json_object_new_int(fanspeed)); + + json_object *query = afb_req_json(request); + afb_req_success_f(request, ret_json, "Fan Speed:%d query=%s", fanspeed, json_object_to_json_string(query)); +} + +/* + * @brief Set fan speed to HVAC system + * + * @param struct afb_req : an afb request structure + * + */ +static void set_fanspeed(struct afb_req request) +{ + struct can_handler ch; + int fanspeed = (int)afb_req_value(request, "FanSpeed"); + + // Set can_payload array with the new fan speed value + can_payload[4] = fanspeed; + + ch = open_can_dev(); + write_can(ch); + close_can_dev(ch); + + json_object *query = afb_req_json(request); + afb_req_success_f(request, NULL, "Fanspeed=%d query=%s", can_payload[4], json_object_to_json_string(query)); +} + +/* + * @brief Read Consign right zone temperature for HVAC system + * + * @param struct afb_req : an afb request structure + * + */ +static void get_temp_right_zone(struct afb_req request) +{ + json_object *ret_json; + int temp = read_temp_right_zone(); + + ret_json = json_object_new_object(); + json_object_object_add(ret_json, "RightTemperature", json_object_new_int(temp)); + + json_object *query = afb_req_json(request); + afb_req_success_f(request, ret_json, "Temperature right zone:%d query=%s", temp, json_object_to_json_string(query)); +} + +/* + * @brief Read Consign left zone temperature for HVAC system + * + * @param struct afb_req : an afb request structure + * + */ +static void get_temp_left_zone(struct afb_req request) +{ + json_object *ret_json; + int temp = read_temp_left_zone(); + + ret_json = json_object_new_object(); + json_object_object_add(ret_json, "LeftTemperature", json_object_new_int(temp)); + + json_object *query = afb_req_json(request); + afb_req_success_f(request, ret_json, "Temperature left zone:%d query=%s", temp, json_object_to_json_string(query)); +} + + +/* + * @brief Set right zone temperature to HVAC system + * + * @param struct afb_req : an afb request structure + * + */ +static void set_temp_right_zone(struct afb_req request) +{ + struct can_handler ch; + int tempright = (int)afb_req_value(request, "RightTemperature"); + + // Set can_payload array with the new fan speed value + can_payload[1] = tempright; + + ch = open_can_dev(); + write_can(ch); + close_can_dev(ch); + + json_object *query = afb_req_json(request); + afb_req_success_f(request, NULL, "Ping Binder Daemon fanspeed=%d query=%s", can_payload[4], json_object_to_json_string(query)); +} + +/* + * @brief Set left zone temperature to HVAC system + * + * @param struct afb_req : an afb request structure + * + */ +static void set_temp_left_zone(struct afb_req request) +{ + struct can_handler ch; + int templeft = (int)afb_req_value(request, "LeftTemperature"); + + // Set can_payload array with the new fan speed value + can_payload[0] = templeft; + + ch = open_can_dev(); + write_can(ch); + close_can_dev(ch); + + json_object *query = afb_req_json(request); + afb_req_success_f(request, NULL, "Ping Binder Daemon fanspeed=%d query=%s", can_payload[4], json_object_to_json_string(query)); +} + +/* + * @brief Read all values + * + * @param struct afb_req : an afb request structure + * + */ +static void get_all(struct afb_req request) +{ + json_object *ret_json; + + ret_json = json_object_new_object(); + json_object_object_add(ret_json, "LeftTemperature", json_object_new_int(read_temp_left_zone())); + json_object_object_add(ret_json, "RightTemperature", json_object_new_int(read_temp_right_zone())); + json_object_object_add(ret_json, "FanSpeed", json_object_new_int(read_fanspeed())); + + afb_req_success_f(request, ret_json, NULL); +} + +// TODO: Have to change session management flag to AFB_SESSION_CHECK to use token auth +static const struct afb_verb_desc_v1 verbs[]= { + {"ping" , AFB_SESSION_NONE, ping , "Ping the binder"}, + {"get_temp_left_zone" , AFB_SESSION_NONE, get_temp_left_zone , "Get the left zone temperature"}, + {"get_temp_right_zone" , AFB_SESSION_NONE, get_temp_right_zone , "Get the right zone temperature"}, + {"set_temp_left_zone" , AFB_SESSION_NONE, set_temp_left_zone , "Set the left zone temperature"}, + {"set_temp_right_zone" , AFB_SESSION_NONE, set_temp_right_zone , "Set the right zone temperature"}, + {"set_fanspeed" , AFB_SESSION_NONE, set_fanspeed , "Set fanspeed"}, + {"get_fanspeed" , AFB_SESSION_NONE, get_fanspeed , "Read fan speed"}, + {"get_all" , AFB_SESSION_NONE, get_all , "Read all values"}, + {NULL} +}; + +static const struct afb_binding plugin_desc = { + .type = AFB_BINDING_VERSION_1, + .v1 = { + .info = "hvac hybrid service", + .prefix = "hvac", + .verbs = verbs + } +}; + +const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf) +{ + interface = itf; + + return &plugin_desc; +} |