Compare commits
2 Commits
e5bb662e58
...
132cea5676
Author | SHA1 | Date | |
---|---|---|---|
132cea5676 | |||
f506723032 |
80
README.md
80
README.md
@ -1,80 +0,0 @@
|
|||||||
# BachelorThesis
|
|
||||||
|
|
||||||
## About
|
|
||||||
This repository contains source codes for client-server network application capable to communicate with distance laser sensor DLS-C 15 via RS-232 interface, which was implemented as a part of bachelor thesis.
|
|
||||||
|
|
||||||
## Author
|
|
||||||
Author: Jozef Simko
|
|
||||||
|
|
||||||
School year: 3., Bachelor study, 2021/22
|
|
||||||
|
|
||||||
Study program: Computer Networks
|
|
||||||
|
|
||||||
Organization: Technical University of Kosice (TUKE), Faculty of Electrical Engineering and Informatics (FEI)
|
|
||||||
|
|
||||||
## Building
|
|
||||||
Implemented and tested on:
|
|
||||||
| Platform | OS | compiler |
|
|
||||||
|-----------------|---------------------------|-------------------------------------------------|
|
|
||||||
| Linux | Ubuntu 20.04.1 WLS2 | gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2) |
|
|
||||||
| Windows | Windows 10.0.19043 | gcc version 11.2.0 (MinGW-W64 x86_64-posix-seh) |
|
|
||||||
| Raspberry Pi | Linux raspberrypi 5.10.17 | gcc version 8.3.0 (Raspbian 8.3.0-6+rpi1) |
|
|
||||||
|
|
||||||
#### LINUX
|
|
||||||
* CLIENT
|
|
||||||
- `gcc client.c -Wall -Werror -Wextra -o client`
|
|
||||||
* SERVER
|
|
||||||
- `gcc server.c rs232.c -Wall -Werroe -Wextra -o server`
|
|
||||||
#### WINDOWS
|
|
||||||
* CLIENT
|
|
||||||
- `gcc client.c -Wall -Wextra -lwsock32 -o client`
|
|
||||||
* SERVER
|
|
||||||
- `gcc server.c rs232.c -lwsock32 -Wall -Werror -Wextra -o server`
|
|
||||||
|
|
||||||
## Launch
|
|
||||||
### Server
|
|
||||||
Server can be launched with 1 or 2 input parameters. The number of parameters determines what mode will be used - manual or automatic mode.
|
|
||||||
|
|
||||||
**port** - specific number to identify communication processes of server
|
|
||||||
|
|
||||||
**[config_file]** - configuration file with exact name of variables - check *config.cfg* file as example
|
|
||||||
|
|
||||||
#### Manual mode
|
|
||||||
- server waits for input commands from client, sends them to laser sensor and returns results back to client
|
|
||||||
- `./server <port>`
|
|
||||||
|
|
||||||
#### Automatic mode
|
|
||||||
- server loads variables from configuration file *config.txt*, starts measuring and sends results to client continuously.
|
|
||||||
- `./server <port> [config_file]`
|
|
||||||
|
|
||||||
### Client
|
|
||||||
Client has to be lauched with 2 input parameters. If server is in **manual mode**, the client always loads input commands from *commands.txt*.
|
|
||||||
|
|
||||||
**IP address** - IP address of server the client tries to connect
|
|
||||||
|
|
||||||
**port** - port number of server
|
|
||||||
- `./client <IP address> <port>`
|
|
||||||
|
|
||||||
## Demo
|
|
||||||
Demo program demonstrates how to create client-like program, which can connect to server in automatic mode and process resulting data.
|
|
||||||
#### Building
|
|
||||||
UNIX - `gcc demo.c -Wall -Werror -Wextra -o demo`
|
|
||||||
|
|
||||||
WINDOWS - `gcc demo.c -Wall -Wextra -lwsock32 -o demo`
|
|
||||||
|
|
||||||
#### Launch
|
|
||||||
No input parameters.
|
|
||||||
|
|
||||||
Macros defines multiple variables:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define IP_ADDRESS "192.168.0.101" // IP address of server
|
|
||||||
#define PORT 32500 // server port number
|
|
||||||
#define MAX_VALUE 1265 // upper limit to compare (depends on used units)
|
|
||||||
#define MIN_VALUE 1200 // lower limit to compare (depends on used units)
|
|
||||||
```
|
|
||||||
|
|
||||||
## References
|
|
||||||
[WinLibs GCC](https://winlibs.com)
|
|
||||||
|
|
||||||
[RS-232 library](https://www.teuniz.net/RS-232/)
|
|
5
client.c
5
client.c
@ -142,7 +142,7 @@ int main(int argc , char *argv[]){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check server's mode
|
// Check server's mode and set control variable
|
||||||
int automatic = 0;
|
int automatic = 0;
|
||||||
if(strcmp(server_reply, "0") == 0){
|
if(strcmp(server_reply, "0") == 0){
|
||||||
printf("Connected - manual mode.\n");
|
printf("Connected - manual mode.\n");
|
||||||
@ -157,12 +157,13 @@ int main(int argc , char *argv[]){
|
|||||||
char *description[CMD_BUF_SIZE];
|
char *description[CMD_BUF_SIZE];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
// Manual mode
|
||||||
if(automatic == 0){
|
if(automatic == 0){
|
||||||
|
|
||||||
// Load user commands
|
// Load user commands
|
||||||
FILE *fptr;
|
FILE *fptr;
|
||||||
if ((fptr = fopen("commands.txt", "r")) == NULL) {
|
if ((fptr = fopen("commands.txt", "r")) == NULL) {
|
||||||
printf("Cannot open/create log file!\n");
|
printf("Cannot open command file!\n");
|
||||||
cleanUP(sock);
|
cleanUP(sock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
94
server.c
94
server.c
@ -52,6 +52,14 @@ first number represents databits, letter defines parity and last number is for s
|
|||||||
It's better to use higher values, it's helpful in case of hardware/RS-232 overload */
|
It's better to use higher values, it's helpful in case of hardware/RS-232 overload */
|
||||||
#define COM_BUFFER 4096
|
#define COM_BUFFER 4096
|
||||||
|
|
||||||
|
/* Amount of seconds used to wait before checking and reading data from RS-232 line
|
||||||
|
Waiting time should be approx. 0,1 seconds (from RS-232 library), but the lowest
|
||||||
|
measure (response) time od distance sensor is 0,3 seconds, the greatest value is 4-5 seconds.
|
||||||
|
Value 1 equals 1 second, which is used in loop checking max response time.
|
||||||
|
This value fit perfectly for this software and should not be changed.
|
||||||
|
*/
|
||||||
|
#define WAIT_TIME 1
|
||||||
|
|
||||||
/* Definition of struct used in main() */
|
/* Definition of struct used in main() */
|
||||||
struct var {
|
struct var {
|
||||||
char *name;
|
char *name;
|
||||||
@ -81,7 +89,7 @@ Returns lasermeter device ID from return value of command "dg"
|
|||||||
char getID(int cport_nr){
|
char getID(int cport_nr){
|
||||||
char dg[] = "dg\r\n";
|
char dg[] = "dg\r\n";
|
||||||
RS232_cputs(cport_nr, dg);
|
RS232_cputs(cport_nr, dg);
|
||||||
wait(1);
|
wait(WAIT_TIME);
|
||||||
|
|
||||||
unsigned char buf[MESSAGE_SIZE];
|
unsigned char buf[MESSAGE_SIZE];
|
||||||
|
|
||||||
@ -331,7 +339,7 @@ int main(int argc , char *argv[]){
|
|||||||
char mode[]="sNc\r\n";
|
char mode[]="sNc\r\n";
|
||||||
mode[1] = deviceID;
|
mode[1] = deviceID;
|
||||||
RS232_cputs(cport_nr, mode);
|
RS232_cputs(cport_nr, mode);
|
||||||
wait(1);
|
wait(WAIT_TIME);
|
||||||
RS232_PollComport(cport_nr, buf, COM_BUFFER);
|
RS232_PollComport(cport_nr, buf, COM_BUFFER);
|
||||||
|
|
||||||
// Automatic mode
|
// Automatic mode
|
||||||
@ -376,25 +384,33 @@ int main(int argc , char *argv[]){
|
|||||||
RS232_cputs(cport_nr, mode);
|
RS232_cputs(cport_nr, mode);
|
||||||
free(mode);
|
free(mode);
|
||||||
|
|
||||||
wait(1);
|
wait(WAIT_TIME);
|
||||||
|
|
||||||
|
// Variables for errors from distance sensor; list of errors, counter of all errors and counter for errors in row
|
||||||
char *errors = malloc(sizeof(char));
|
char *errors = malloc(sizeof(char));
|
||||||
int errCount = 0;
|
int errCount = 0;
|
||||||
int errInRow = 0;
|
int errInRow = 0;
|
||||||
int maxErrors = getVar(vars, "maxErrors");
|
int maxErrors = getVar(vars, "maxErrors");
|
||||||
int samples = getVar(vars, "samples");
|
int samples = getVar(vars, "samples");
|
||||||
|
|
||||||
|
// Counter for samples; value is checked if variable 'samples' is greater than -1 (set in config)
|
||||||
int measureSamples = 0;
|
int measureSamples = 0;
|
||||||
|
|
||||||
|
// Control variable for error linked with client connection, changes to 1 if error is found later in conditions
|
||||||
int e = 0;
|
int e = 0;
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
|
// If amount of errors in row (not interrupted by correct value) reach the limit
|
||||||
if(errInRow >= maxErrors){
|
if(errInRow >= maxErrors){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If max samples variable is set in config and all samples reach the limit
|
||||||
if(samples > -1 && samples == measureSamples){
|
if(samples > -1 && samples == measureSamples){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If client connection error occured
|
||||||
if(e == 1){
|
if(e == 1){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -411,7 +427,39 @@ int main(int argc , char *argv[]){
|
|||||||
char *first = NULL;
|
char *first = NULL;
|
||||||
printf("%s", buf);
|
printf("%s", buf);
|
||||||
|
|
||||||
|
/* EXPERIMENTAL CODE (not tested)
|
||||||
|
It happens that sometimes server receives measured value splitted in two halfs.
|
||||||
|
- it looks like g1g+112\r\n61444\r\n
|
||||||
|
Following code block demonstrates design of code which can solve this problem.
|
||||||
|
|
||||||
|
char halfs[14] = {0};
|
||||||
|
int halfcount = 0;
|
||||||
|
|
||||||
|
// has to change loop(X) condition
|
||||||
|
while ((first = strtok_r(rest, "\n", &rest))){
|
||||||
|
first[strcspn(token, "\r")] = 0;
|
||||||
|
|
||||||
|
int checkLen = (int)strlen(first);
|
||||||
|
if(checkLen < 12){
|
||||||
|
if(halfcount == 0){
|
||||||
|
strcpy(halfs, first);
|
||||||
|
halfcount++;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
strcat(halfs, first);
|
||||||
|
halfcount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first = halfs;
|
||||||
|
...
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// Split and handle data
|
// Split and handle data
|
||||||
|
// Loop(X)
|
||||||
while((first = strtok_r(rest, "\r\n", &rest))){
|
while((first = strtok_r(rest, "\r\n", &rest))){
|
||||||
// Check and handle error
|
// Check and handle error
|
||||||
char *err = NULL;
|
char *err = NULL;
|
||||||
@ -432,16 +480,30 @@ int main(int argc , char *argv[]){
|
|||||||
}
|
}
|
||||||
// Handle other values
|
// Handle other values
|
||||||
else{
|
else{
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
if((res = atoi(first)) > 0){
|
/* // EXPERIMENTAL (untested) function
|
||||||
res = atoi(first);
|
// Check if output result doesnt have incorrect lenght (devided to 2 halfs)
|
||||||
}
|
|
||||||
else{
|
first[strcspn(token, "\r")] = 0;
|
||||||
char *numbers = NULL;
|
|
||||||
strtok_r(first, "+", &numbers);
|
int checkLen = (int)strlen(first);
|
||||||
res = atoi(numbers);
|
if(checkLen < 12){
|
||||||
}
|
if(halfcount == 0){
|
||||||
|
strcpy(halfs, first);
|
||||||
|
halfcount++;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
strcat(halfs, first);
|
||||||
|
halfcount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first = halfs;
|
||||||
|
*/
|
||||||
|
// Change string to integer
|
||||||
|
int res = 0;
|
||||||
|
char *numbers = NULL;
|
||||||
|
strtok_r(first, "+", &numbers);
|
||||||
|
res = atoi(numbers);
|
||||||
|
|
||||||
|
|
||||||
if(res == 0){
|
if(res == 0){
|
||||||
@ -450,10 +512,12 @@ int main(int argc , char *argv[]){
|
|||||||
|
|
||||||
int units = getVar(vars, "units");
|
int units = getVar(vars, "units");
|
||||||
|
|
||||||
|
// Change integer to double and apply set units
|
||||||
double resd = res * (1/(double)units);
|
double resd = res * (1/(double)units);
|
||||||
char output[MESSAGE_SIZE];
|
char output[MESSAGE_SIZE];
|
||||||
memset(output, 0, MESSAGE_SIZE);
|
memset(output, 0, MESSAGE_SIZE);
|
||||||
|
|
||||||
|
// Add time stamp to result
|
||||||
snprintf(output, MESSAGE_SIZE, "%02d/%02d/%d - %02d:%02d:%02d: %0.2f\n", timeinfo->tm_mday, timeinfo->tm_mon+1, timeinfo->tm_year+1900,
|
snprintf(output, MESSAGE_SIZE, "%02d/%02d/%d - %02d:%02d:%02d: %0.2f\n", timeinfo->tm_mday, timeinfo->tm_mon+1, timeinfo->tm_year+1900,
|
||||||
timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, resd);
|
timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, resd);
|
||||||
|
|
||||||
@ -486,7 +550,7 @@ int main(int argc , char *argv[]){
|
|||||||
|
|
||||||
}
|
}
|
||||||
// Automatic mode end sequence
|
// Automatic mode end sequence
|
||||||
wait(1);
|
wait(WAIT_TIME);
|
||||||
char stop[] = "sNc\r\n";
|
char stop[] = "sNc\r\n";
|
||||||
stop[1] = deviceID;
|
stop[1] = deviceID;
|
||||||
RS232_cputs(cport_nr, stop);
|
RS232_cputs(cport_nr, stop);
|
||||||
@ -498,7 +562,7 @@ int main(int argc , char *argv[]){
|
|||||||
send(client_sock, end, 1, 0);
|
send(client_sock, end, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
wait(1);
|
wait(WAIT_TIME);
|
||||||
printf("End of measuring, shutting down server.\n");
|
printf("End of measuring, shutting down server.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -514,7 +578,7 @@ int main(int argc , char *argv[]){
|
|||||||
|
|
||||||
int checkCOM = 0;
|
int checkCOM = 0;
|
||||||
while(RS232_PollComport(cport_nr, buf, COM_BUFFER) <= 0){
|
while(RS232_PollComport(cport_nr, buf, COM_BUFFER) <= 0){
|
||||||
wait(1);
|
wait(WAIT_TIME);
|
||||||
if(checkCOM == 5){
|
if(checkCOM == 5){
|
||||||
char info[] = "No response from COM port, check your device and all cables!\n";
|
char info[] = "No response from COM port, check your device and all cables!\n";
|
||||||
send(client_sock, info, strlen(info), 0);
|
send(client_sock, info, strlen(info), 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user