blob: 8b3bdf863ee1ac3cd3af5bc4619c228953e50609 [file] [log] [blame]
/*
* Copyright (c) 2017 FH Dortmund and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Description:
* Socket client for rover-app to rover-web communication
*
* Contributors:
* M.Ozcelikors <mozcelikors@gmail.com>, created 26.10.2017
*
*/
#include <tasks/socket_client_task.h>
#include <unistd.h>
#include <ctime>
#include <libraries/timing/timing.h>
#include <interfaces.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
/* Signal header */
#include <signal.h>
/* Socket defs header */
#include <socket_settings.h>
/* json-cpp library */
#include <json/json.h>
#include <math.h>
#include <roverapp.h>
/* Global definitions */
int roverapp_send_sockfd;
/* If returns nonzero -> socket has a non zero error status */
int checkClientSocketStatus (int socket_fd)
{
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);
return error;
}
Json::Value constructJSONData (int data_type)
{
Json::Value data;
switch (data_type)
{
case SENSOR_DATA:
data["rover_dtype"] = "sensor";
data["data"]["infrared0"] = ceil(infrared_shared[0]);
data["data"]["infrared1"] = ceil(infrared_shared[1]);
data["data"]["infrared2"] = ceil(infrared_shared[2]);
data["data"]["infrared3"] = ceil (infrared_shared[3]);
data["data"]["front"] = ceil (distance_sr04_front_shared);
data["data"]["rear"] = ceil (distance_sr04_back_shared);
data["data"]["temperature"] = ceil (temperature_shared);
data["data"]["humidity"] = ceil (humidity_shared);
data["data"]["bearing"] = ceil (bearing_shared);
break;
case UTIL_DATA:
data["rover_dtype"] = "util";
data["data"]["core0"] = cpu_util_shared[0];
data["data"]["core1"] = cpu_util_shared[1];
data["data"]["core2"] = cpu_util_shared[2];
data["data"]["core3"] = cpu_util_shared[3];
break;
default:
data["rover_dtype"] = "none";
break;
}
return data;
}
void Socket_Client_Task_Terminator (int dummy)
{
close(roverapp_send_sockfd);
running_flag = 0;
}
void *Socket_Client_Task (void * arg)
{
timing socket_client_task_tmr;
socket_client_task_tmr.setTaskID("Socket_Client_Task");
socket_client_task_tmr.setDeadline(0.5);
socket_client_task_tmr.setPeriod(0.5);
/* Add termination signal handler to properly close socket */
signal(SIGINT, Socket_Client_Task_Terminator);
signal(SIGTERM, Socket_Client_Task_Terminator);
signal(SIGKILL, Socket_Client_Task_Terminator);
/* Socket related initializations */
int n;
struct sockaddr_in serv_addr;
struct hostent *server;
char client_buffer[JSON_DATA_BUFSIZE];
char * eof_str = "\r\n";
int connected_flag = 0;
/* Send these data each iteration*/
int job_count = 2;
int job_list[job_count] = {SENSOR_DATA, UTIL_DATA};
int job_idx = 0;
/* Create JSON object to hold sensor data */
Json::FastWriter string_writer;
while (running_flag)
{
socket_client_task_tmr.recordStartTime();
socket_client_task_tmr.calculatePreviousSlackTime();
//Task content starts here -----------------------------------------------
/* For Connecting / Reconnecting */
if (checkClientSocketStatus(roverapp_send_sockfd)!=0)
{
connected_flag = 0;
}
if (connected_flag == 0)
{
/* Try to connect or reconnect */
/* Create socket, and connect to the socket */
close(roverapp_send_sockfd);
roverapp_send_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (roverapp_send_sockfd < 0)
perror("ERROR opening socket");
server = gethostbyname(CONNECTION_HOSTNAME);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(ROVERAPP_SEND_PORT);
/* Try to connect */
if (connect(roverapp_send_sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) == 0)
{
connected_flag = 1;
job_idx = 0;
}
}
else
{
/* Connected, start writing */
/* Construct the JSON data and Write to string */
std::string temp = string_writer.write(constructJSONData(job_list[job_idx++]));
if (job_idx == job_count)
job_idx = 0;
/* Clear buffer and Write to buffer from string */
bzero(client_buffer, JSON_DATA_BUFSIZE);
if (strncpy(client_buffer, temp.c_str(), sizeof(client_buffer)) == NULL)
{
perror("strcpy temp");
}
client_buffer[sizeof(client_buffer)-1] = 0;
/* Attach end of file character to string*/
if (strcat(client_buffer, eof_str) == NULL)
{
perror("strcat EOF");
}
/* Write to socket */
if (write(roverapp_send_sockfd, client_buffer, strlen(client_buffer)) == -1)
{
perror("write");
/* Very important approach to have re-usable socket client */
/* Checking connection status by using exit status of 'write' */
printf ("Disconnected from server : socket_client.cpp");
connected_flag = 0;
}
}
//Task content ends here -------------------------------------------------
socket_client_task_tmr.recordEndTime();
socket_client_task_tmr.calculateExecutionTime();
socket_client_task_tmr.calculateDeadlineMissPercentage();
socket_client_task_tmr.incrementTotalCycles();
pthread_mutex_lock(&socket_client_task_ti_l);
socket_client_task_ti.deadline = socket_client_task_tmr.getDeadline();
socket_client_task_ti.deadline_miss_percentage = socket_client_task_tmr.getDeadlineMissPercentage();
socket_client_task_ti.execution_time = socket_client_task_tmr.getExecutionTime();
socket_client_task_ti.period = socket_client_task_tmr.getPeriod();
socket_client_task_ti.prev_slack_time = socket_client_task_tmr.getPrevSlackTime();
socket_client_task_ti.task_id = socket_client_task_tmr.getTaskID();
socket_client_task_ti.start_time = socket_client_task_tmr.getStartTime();
socket_client_task_ti.end_time = socket_client_task_tmr.getEndTime();
pthread_mutex_unlock(&socket_client_task_ti_l);
socket_client_task_tmr.sleepToMatchPeriod();
}
/* the function must return something - NULL will do */
return NULL;
}