Revive from archive.
This commit is contained in:
commit
ec25470914
27
TCP/Makefile
Executable file
27
TCP/Makefile
Executable file
@ -0,0 +1,27 @@
|
||||
SOURCES = $(wildcard *.c)
|
||||
TARGET = tcp
|
||||
|
||||
# top-level rule, to compile everything.
|
||||
all: $(TARGET)
|
||||
|
||||
DEPS = $(wildcard *.d)
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
#link
|
||||
$(TARGET): $(OBJECTS)
|
||||
gcc -o $@ $^ -lpthread -g
|
||||
|
||||
#compile
|
||||
%.o : %.c
|
||||
gcc -o $@ $< -c -g -MMD -Wall
|
||||
|
||||
# If explicit dependencies exist, add them
|
||||
include $(DEPS)
|
||||
|
||||
# rule for cleaning re-compilable files.
|
||||
clean:
|
||||
rm -f $(TARGET) $(OBJECTS) $(DEPS)
|
||||
|
||||
rebuild: clean all
|
||||
|
||||
.PHONY: rebuild clean all
|
||||
89
TCP/main.c
Executable file
89
TCP/main.c
Executable file
@ -0,0 +1,89 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "tcp.h"
|
||||
|
||||
#define LINE_SIZE 256
|
||||
|
||||
typedef void *(*thread_t)(void*);
|
||||
typedef void *thread_param_t;
|
||||
|
||||
void *receive_thread(socket_fd_t socket)
|
||||
{
|
||||
while (1){
|
||||
int chr;
|
||||
|
||||
int s = recv(socket, &chr, 1, 0);
|
||||
|
||||
if (s < 0) {
|
||||
perror("receive_thread (recv):");
|
||||
close(socket);
|
||||
exit(1);
|
||||
}
|
||||
else if (s == 0) {
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
putchar(chr);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t recv_thread;
|
||||
socket_fd_t socket;
|
||||
char *tmp;
|
||||
int port;
|
||||
char line[LINE_SIZE];
|
||||
|
||||
if (argc < 2) {
|
||||
printf("tcp: not enough input arguments\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((tmp = strchr(argv[1], ':'))) {
|
||||
port = atoi(tmp+1);
|
||||
*tmp = '\0';
|
||||
|
||||
printf("Assuming client mode: Host:%s, Port:%d\n", argv[1], port);
|
||||
|
||||
socket = tcp_connect(argv[1], port);
|
||||
}
|
||||
else {
|
||||
port = atoi(argv[1]);
|
||||
|
||||
printf("Assuming server mode: Port:%d\n", port);
|
||||
|
||||
socket = tcp_accept(port);
|
||||
}
|
||||
|
||||
if (socket < 0) {
|
||||
return socket;
|
||||
}
|
||||
|
||||
/*START*/
|
||||
|
||||
pthread_create(&recv_thread, NULL, (thread_t)&receive_thread,
|
||||
(thread_param_t)socket);
|
||||
|
||||
while (1) {
|
||||
fgets(line, sizeof(line), stdin);
|
||||
|
||||
if (write(socket, line, strlen(line)) != strlen(line)) {
|
||||
perror("main (write):");
|
||||
close(socket);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
110
TCP/tcp.c
Executable file
110
TCP/tcp.c
Executable file
@ -0,0 +1,110 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
//#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "tcp.h"
|
||||
|
||||
|
||||
struct sockaddr_in init_sockaddr_in(int port) {
|
||||
struct sockaddr_in r;
|
||||
|
||||
r.sin_family = AF_INET;
|
||||
r.sin_addr.s_addr = INADDR_ANY;
|
||||
r.sin_port = htons(port);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct sockaddr *hostent2sockaddr(struct hostent *e, int port) {
|
||||
static struct sockaddr_in sa;
|
||||
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
memcpy(&sa.sin_addr.s_addr, e->h_addr, e->h_length);
|
||||
|
||||
return (struct sockaddr*)&sa;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void my_setsockopt(int socket, int option, int value)
|
||||
{
|
||||
setsockopt(socket, SOL_SOCKET, option, &value, sizeof(value));
|
||||
}
|
||||
|
||||
|
||||
|
||||
socket_fd_t tcp_connect(const char *server_name, int port)
|
||||
{
|
||||
socket_fd_t comm_socket;
|
||||
struct sockaddr *serv_addr = NULL;
|
||||
struct hostent *server = NULL;
|
||||
|
||||
if ((comm_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
|
||||
perror("connect (socket)");
|
||||
return ERR_CANT_CREATE_SOCKET;
|
||||
}
|
||||
|
||||
if ((server = gethostbyname(server_name)) == NULL) {
|
||||
perror("connect (gethostbyname)");
|
||||
return ERR_INVALID_HOST;
|
||||
}
|
||||
|
||||
printf("%s \n", *server);
|
||||
|
||||
serv_addr = hostent2sockaddr(server, port);
|
||||
|
||||
if (connect(comm_socket, serv_addr, sizeof(*serv_addr)) < 0) {
|
||||
perror("connect (connect)");
|
||||
return ERR_CANT_CONNECT;
|
||||
}
|
||||
|
||||
return comm_socket;
|
||||
}
|
||||
|
||||
|
||||
|
||||
socket_fd_t tcp_accept(int port)
|
||||
{
|
||||
socket_fd_t accept_socket, comm_socket;
|
||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in serv_addr = init_sockaddr_in(port);
|
||||
struct sockaddr_in cli_addr = init_sockaddr_in(0);
|
||||
|
||||
if ((accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
|
||||
perror("accept (socket)");
|
||||
return ERR_CANT_CREATE_SOCKET;
|
||||
}
|
||||
|
||||
my_setsockopt(accept_socket, SO_REUSEADDR, 1);
|
||||
|
||||
if (bind(accept_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
|
||||
perror("accept (bind)");
|
||||
close(accept_socket);
|
||||
return ERR_CANT_BIND_SOCKET;
|
||||
}
|
||||
|
||||
if (listen(accept_socket, 255) < 0) {
|
||||
perror("accept (listen)");
|
||||
close(accept_socket);
|
||||
return ERR_CANT_LISTEN;
|
||||
}
|
||||
|
||||
if ((comm_socket = accept(accept_socket, (struct sockaddr *)&cli_addr, &addrlen)) < 0) {
|
||||
perror("accept (accept)");
|
||||
return ERR_CANT_ACCEPT;
|
||||
}
|
||||
|
||||
close(accept_socket);
|
||||
return comm_socket;
|
||||
}
|
||||
|
||||
16
TCP/tcp.h
Executable file
16
TCP/tcp.h
Executable file
@ -0,0 +1,16 @@
|
||||
#define ERR_INVALID_HOST -1
|
||||
#define ERR_CANT_CREATE_SOCKET -2
|
||||
#define ERR_CANT_WRITE -3
|
||||
#define ERR_CANT_CONNECT -4
|
||||
#define ERR_CANT_CREATE_THREAD -5
|
||||
#define ERR_CANT_GET_BROADCAST_ADDR -6
|
||||
#define ERR_CANT_BIND_SOCKET -7
|
||||
#define ERR_INVALID_DEVICE -8
|
||||
#define ERR_CANT_LISTEN -9
|
||||
#define ERR_CANT_ACCEPT -10
|
||||
|
||||
typedef int socket_fd_t;
|
||||
|
||||
socket_fd_t tcp_connect(const char* server, int port);
|
||||
socket_fd_t tcp_accept(int port);
|
||||
|
||||
27
UDP/Makefile
Executable file
27
UDP/Makefile
Executable file
@ -0,0 +1,27 @@
|
||||
SOURCES = $(wildcard *.c)
|
||||
TARGET = udp
|
||||
|
||||
# top-level rule, to compile everything.
|
||||
all: $(TARGET)
|
||||
|
||||
DEPS = $(wildcard *.d)
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
#link
|
||||
$(TARGET): $(OBJECTS)
|
||||
gcc -o $@ $^ -lpthread -g
|
||||
|
||||
#compile
|
||||
%.o : %.c
|
||||
gcc -o $@ $< -c -g -MMD -Wall
|
||||
|
||||
# If explicit dependencies exist, add them
|
||||
include $(DEPS)
|
||||
|
||||
# rule for cleaning re-compilable files.
|
||||
clean:
|
||||
rm -f $(TARGET) $(OBJECTS) $(DEPS)
|
||||
|
||||
rebuild: clean all
|
||||
|
||||
.PHONY: rebuild clean all
|
||||
67
UDP/main.c
Executable file
67
UDP/main.c
Executable file
@ -0,0 +1,67 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "udp.h"
|
||||
|
||||
#define LINE_SIZE 256
|
||||
|
||||
|
||||
static void receive_function(udp_packet_t packet)
|
||||
{
|
||||
putchar(packet);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int port;
|
||||
char line[LINE_SIZE];
|
||||
char server[100];
|
||||
|
||||
if (argc < 2) {
|
||||
printf("udp: not enough input arguments\n");
|
||||
return 1;
|
||||
}
|
||||
else if (!strchr(argv[1], ':')) {
|
||||
printf(
|
||||
"Usage:\n"
|
||||
" udp target:port\n"
|
||||
"or:\n"
|
||||
" udp broadcast:port\n"
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
port = atoi(strchr(argv[1], ':')+1);
|
||||
*strchr(argv[1], ':') = '\0';
|
||||
|
||||
if (!strcmp(argv[1], "broadcast")) {
|
||||
if (udp_get_broadcast_address("eth1", server, sizeof(server)) < 0) {
|
||||
printf("Error: Cannot determine broadcast address\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strncpy(server, argv[1], sizeof(server));
|
||||
}
|
||||
|
||||
printf("Using %s:%d\n", server, port);
|
||||
|
||||
udp_listen(port, &receive_function);
|
||||
|
||||
while (1) {
|
||||
int i;
|
||||
fgets(line, LINE_SIZE, stdin);
|
||||
|
||||
for (i = 0; line[i] != '\0'; i++) {
|
||||
udp_packet_t packet = line[i];
|
||||
udp_send_packet(server, port, packet);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
191
UDP/udp.c
Executable file
191
UDP/udp.c
Executable file
@ -0,0 +1,191 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "udp.h"
|
||||
|
||||
typedef void *(*thread_t)(void*);
|
||||
typedef void *thread_param_t;
|
||||
|
||||
typedef struct tag_listen_info
|
||||
{
|
||||
int port;
|
||||
void (*receiving_function)(udp_packet_t);
|
||||
} listen_info_t;
|
||||
|
||||
|
||||
|
||||
int udp_get_broadcast_address(const char *network_interface, char *broadcast_address, int address_buffer_length)
|
||||
{
|
||||
int sockfd = -1;
|
||||
struct ifreq ifr;
|
||||
|
||||
// Start referanse-socket
|
||||
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||
perror("get_broadcast_addr (socket)");
|
||||
return ERR_CANT_CREATE_SOCKET;
|
||||
}
|
||||
|
||||
strncpy (ifr.ifr_name, network_interface, sizeof(ifr.ifr_name));
|
||||
|
||||
// Hent broadcast adresse fra ioctl()
|
||||
if (ioctl(sockfd, SIOCGIFBRDADDR, &ifr) != 0) {
|
||||
perror("get_broadcast_addr (ioctl)");
|
||||
return ERR_CANT_GET_BROADCAST_ADDR;
|
||||
}
|
||||
|
||||
if ( ifr.ifr_broadaddr.sa_family != AF_INET ) {
|
||||
fputs("Not IPV4 network interface", stderr);
|
||||
return ERR_INVALID_DEVICE;
|
||||
}
|
||||
|
||||
strncpy(
|
||||
broadcast_address,
|
||||
inet_ntoa(((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr),
|
||||
address_buffer_length);
|
||||
|
||||
broadcast_address[address_buffer_length-1] = '\0';
|
||||
|
||||
close(sockfd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void udp_abort_listen(int thread)
|
||||
{
|
||||
pthread_cancel( thread );
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *udp_listen_thread(listen_info_t *listen_info_ptr)
|
||||
{
|
||||
int sockfd, n;
|
||||
struct sockaddr_in serv_addr;
|
||||
udp_packet_t packet;
|
||||
listen_info_t li = *listen_info_ptr;
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||
perror("listen (socket)");
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
{
|
||||
int dummy=1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &dummy, sizeof(dummy));
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &dummy, sizeof(dummy));
|
||||
}
|
||||
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
serv_addr.sin_port = htons(li.port);
|
||||
|
||||
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
|
||||
perror("listen (bind)");
|
||||
close(sockfd);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
n = recvfrom(sockfd, &packet, sizeof(packet), 0, 0, 0);
|
||||
|
||||
if (n < 0)
|
||||
fprintf(stderr, "ERROR reading from socket\n");
|
||||
|
||||
li.receiving_function(packet);
|
||||
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int udp_listen(int port, void (*receiving_function)(udp_packet_t))
|
||||
{
|
||||
static listen_info_t li;
|
||||
pthread_t new_thread;
|
||||
|
||||
li.port = port;
|
||||
li.receiving_function = receiving_function;
|
||||
|
||||
if (pthread_create(&new_thread, NULL, (thread_t)&udp_listen_thread,
|
||||
(thread_param_t)&li) != 0) {
|
||||
perror ("listen (pthread_create)");
|
||||
return ERR_CANT_CREATE_THREAD;
|
||||
}
|
||||
else {
|
||||
return new_thread;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int udp_send_packet(const char addr[256], int port, udp_packet_t packet)
|
||||
{
|
||||
int sockfd;
|
||||
struct sockaddr_in serv_addr;
|
||||
struct hostent *server;
|
||||
|
||||
server = gethostbyname(addr);
|
||||
|
||||
if (server == NULL) {
|
||||
perror("send (gethostbyname)");
|
||||
return ERR_INVALID_HOST;
|
||||
}
|
||||
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
|
||||
serv_addr.sin_family = AF_INET;
|
||||
|
||||
memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
|
||||
|
||||
serv_addr.sin_port = htons(port);
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||
perror("send (socket)");
|
||||
return ERR_CANT_CREATE_SOCKET;
|
||||
}
|
||||
|
||||
{
|
||||
int dummy=1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &dummy, sizeof(dummy));
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &dummy, sizeof(dummy));
|
||||
}
|
||||
|
||||
if (connect(sockfd, (void*)(&serv_addr), sizeof(serv_addr)) < 0) {
|
||||
perror("send (connect)");
|
||||
close(sockfd);
|
||||
return ERR_CANT_CONNECT;
|
||||
}
|
||||
|
||||
if (write(sockfd, &packet, sizeof(packet)) != sizeof(packet)) {
|
||||
perror("send (write)");
|
||||
close(sockfd);
|
||||
return ERR_CANT_WRITE;
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
22
UDP/udp.h
Executable file
22
UDP/udp.h
Executable file
@ -0,0 +1,22 @@
|
||||
#ifndef __INCLUDE_COMM_UDP_H__
|
||||
#define __INCLUDE_COMM_UDP_H__
|
||||
|
||||
#define ERR_INVALID_HOST -1
|
||||
#define ERR_CANT_CREATE_SOCKET -2
|
||||
#define ERR_CANT_WRITE -3
|
||||
#define ERR_CANT_CONNECT -4
|
||||
#define ERR_CANT_CREATE_THREAD -5
|
||||
#define ERR_CANT_GET_BROADCAST_ADDR -6
|
||||
#define ERR_INVALID_DEVICE -7
|
||||
|
||||
typedef unsigned long int udp_packet_t;
|
||||
|
||||
void udp_abort_listen(int thread);
|
||||
int udp_send_packet(const char addr[256], int port, udp_packet_t packet);
|
||||
int udp_listen(int port, void (*receiving_function)(udp_packet_t));
|
||||
|
||||
int udp_get_broadcast_address(const char *network_interface,
|
||||
char *broadcast_address, int address_buffer_length);
|
||||
|
||||
#endif // #ifndef __INCLUDE_COMM_UDP_H__
|
||||
|
||||
27
elev-threaded/Makefile
Executable file
27
elev-threaded/Makefile
Executable file
@ -0,0 +1,27 @@
|
||||
SOURCES = $(wildcard *.c)
|
||||
TARGET = heis
|
||||
|
||||
# top-level rule, to compile everything.
|
||||
all: $(TARGET)
|
||||
|
||||
DEPS = $(wildcard *.d)
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
#link
|
||||
$(TARGET): $(OBJECTS)
|
||||
gcc -o $@ $^ -lpthread -g -lcomedi -lm
|
||||
|
||||
#compile
|
||||
%.o : %.c
|
||||
gcc -o $@ $< -c -g -MMD -Wall
|
||||
|
||||
# If explicit dependencies exist, add them
|
||||
include $(DEPS)
|
||||
|
||||
# rule for cleaning re-compilable files.
|
||||
clean:
|
||||
rm -f $(TARGET) $(OBJECTS) $(DEPS)
|
||||
|
||||
rebuild: clean all
|
||||
|
||||
.PHONY: rebuild clean all
|
||||
62
elev-threaded/channels.h
Executable file
62
elev-threaded/channels.h
Executable file
@ -0,0 +1,62 @@
|
||||
// Channel definitions for elevator control using LibComedi
|
||||
//
|
||||
// 2006, Martin Korsgaard
|
||||
#ifndef __INCLUDE_DRIVER_CHANNELS_H__
|
||||
#define __INCLUDE_DRIVER_CHANNELS_H__
|
||||
|
||||
//in port 4
|
||||
#define PORT4 3
|
||||
#define OBSTRUCTION (0x300+23)
|
||||
#define STOP (0x300+22)
|
||||
#define FLOOR_COMMAND1 (0x300+21)
|
||||
#define FLOOR_COMMAND2 (0x300+20)
|
||||
#define FLOOR_COMMAND3 (0x300+19)
|
||||
#define FLOOR_COMMAND4 (0x300+18)
|
||||
#define FLOOR_UP1 (0x300+17)
|
||||
#define FLOOR_UP2 (0x300+16)
|
||||
|
||||
//in port 1
|
||||
#define PORT1 2
|
||||
#define FLOOR_DOWN2 (0x200+0)
|
||||
#define FLOOR_UP3 (0x200+1)
|
||||
#define FLOOR_DOWN3 (0x200+2)
|
||||
#define FLOOR_DOWN4 (0x200+3)
|
||||
#define SENSOR1 (0x200+4)
|
||||
#define SENSOR2 (0x200+5)
|
||||
#define SENSOR3 (0x200+6)
|
||||
#define SENSOR4 (0x200+7)
|
||||
|
||||
//out port 3
|
||||
#define PORT3 3
|
||||
#define MOTORDIR (0x300+15)
|
||||
#define LIGHT_STOP (0x300+14)
|
||||
#define LIGHT_COMMAND1 (0x300+13)
|
||||
#define LIGHT_COMMAND2 (0x300+12)
|
||||
#define LIGHT_COMMAND3 (0x300+11)
|
||||
#define LIGHT_COMMAND4 (0x300+10)
|
||||
#define LIGHT_UP1 (0x300+9)
|
||||
#define LIGHT_UP2 (0x300+8)
|
||||
|
||||
//out port 2
|
||||
#define PORT2 3
|
||||
#define LIGHT_DOWN2 (0x300+7)
|
||||
#define LIGHT_UP3 (0x300+6)
|
||||
#define LIGHT_DOWN3 (0x300+5)
|
||||
#define LIGHT_DOWN4 (0x300+4)
|
||||
#define DOOR_OPEN (0x300+3)
|
||||
#define FLOOR_IND2 (0x300+1)
|
||||
#define FLOOR_IND1 (0x300+0)
|
||||
|
||||
//out port 0
|
||||
#define PORT0 1
|
||||
#define MOTOR (0x100+0)
|
||||
|
||||
//non-existing ports (to achieve macro consistency)
|
||||
#define FLOOR_DOWN1 -1
|
||||
#define FLOOR_UP4 -1
|
||||
#define LIGHT_DOWN1 -1
|
||||
#define LIGHT_UP4 -1
|
||||
|
||||
|
||||
|
||||
#endif //#ifndef __INCLUDE_DRIVER_CHANNELS_H__
|
||||
237
elev-threaded/elev.c
Executable file
237
elev-threaded/elev.c
Executable file
@ -0,0 +1,237 @@
|
||||
// Wrapper for libComedi Elevator control.
|
||||
// These functions provides an interface to the elevators in the real time lab
|
||||
//
|
||||
// 2006, Martin Korsgaard
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "channels.h"
|
||||
#include "elev.h"
|
||||
#include "io.h"
|
||||
|
||||
#define POLLING_INTERVAL 50000
|
||||
|
||||
// Number of signals and lamps per floor (signals includes stop, obstr)
|
||||
#define N_SIGNALS 6
|
||||
#define N_LAMPS 3
|
||||
|
||||
|
||||
// Array of callback associations.
|
||||
static void (*callbacks_g[N_SIGNALS])(int, int);
|
||||
|
||||
|
||||
|
||||
// Matrix of lamp channels indexed by floor and lamp type.
|
||||
static const int lamp_channel_matrix[N_FLOORS][N_LAMPS] = {
|
||||
{LIGHT_UP1, LIGHT_DOWN1, LIGHT_COMMAND1},
|
||||
{LIGHT_UP2, LIGHT_DOWN2, LIGHT_COMMAND2},
|
||||
{LIGHT_UP3, LIGHT_DOWN3, LIGHT_COMMAND3},
|
||||
{LIGHT_UP4, LIGHT_DOWN4, LIGHT_COMMAND4}};
|
||||
|
||||
|
||||
|
||||
// Matrix of elevator signals channels indexed by floor and signal type.
|
||||
static const int signal_channel_matrix[N_FLOORS][N_SIGNALS] = {
|
||||
{FLOOR_UP1, FLOOR_DOWN1, FLOOR_COMMAND1, SENSOR1, STOP, OBSTRUCTION},
|
||||
{FLOOR_UP2, FLOOR_DOWN2, FLOOR_COMMAND2, SENSOR2, STOP, OBSTRUCTION},
|
||||
{FLOOR_UP3, FLOOR_DOWN3, FLOOR_COMMAND3, SENSOR3, STOP, OBSTRUCTION},
|
||||
{FLOOR_UP4, FLOOR_DOWN4, FLOOR_COMMAND4, SENSOR4, STOP, OBSTRUCTION}};
|
||||
|
||||
|
||||
|
||||
void elev_set_speed(int speed)
|
||||
{
|
||||
// In order to sharply stop the elevator, the direction bit is toggled
|
||||
// before setting speed to zero.
|
||||
static int last_speed = 0;
|
||||
|
||||
// If to start (speed > 0)
|
||||
if (speed > 0)
|
||||
io_clear_bit(MOTORDIR);
|
||||
else if (speed < 0)
|
||||
io_set_bit(MOTORDIR);
|
||||
|
||||
// If to stop (speed == 0)
|
||||
else if (last_speed < 0)
|
||||
io_clear_bit(MOTORDIR);
|
||||
else if (last_speed > 0)
|
||||
io_set_bit(MOTORDIR);
|
||||
|
||||
last_speed = speed ;
|
||||
|
||||
// Write new setting to motor.
|
||||
io_write_analog(MOTOR, 2048 + 2*abs(speed));
|
||||
|
||||
//printf(__FILE__ ": Speed set to %d\n", speed);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void elev_set_door_open_lamp(int value)
|
||||
{
|
||||
if (value)
|
||||
io_set_bit(DOOR_OPEN);
|
||||
else
|
||||
io_clear_bit(DOOR_OPEN);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void elev_set_stop_lamp(int value)
|
||||
{
|
||||
if (value)
|
||||
io_set_bit(LIGHT_STOP);
|
||||
else
|
||||
io_clear_bit(LIGHT_STOP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void elev_set_floor_indicator(int floor)
|
||||
{
|
||||
assert(floor >= 0);
|
||||
assert(floor < N_FLOORS);
|
||||
|
||||
if (floor & 0x02)
|
||||
io_set_bit(FLOOR_IND1);
|
||||
else
|
||||
io_clear_bit(FLOOR_IND1);
|
||||
|
||||
if (floor & 0x01)
|
||||
io_set_bit(FLOOR_IND2);
|
||||
else
|
||||
io_clear_bit(FLOOR_IND2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void elev_set_button_lamp(elev_direction_t lamp, int floor, int value)
|
||||
{
|
||||
assert(floor >= 0);
|
||||
assert(floor < N_FLOORS);
|
||||
|
||||
if (value == 1)
|
||||
io_set_bit(lamp_channel_matrix[floor][lamp]);
|
||||
else
|
||||
io_clear_bit(lamp_channel_matrix[floor][lamp]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void elev_unregister_callback(elev_signal_t type)
|
||||
{
|
||||
callbacks_g[type] = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void elev_register_callback(elev_signal_t type, void (*callback)(int, int))
|
||||
{
|
||||
callbacks_g[type] = callback;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void elev_disable_callbacks(int thread)
|
||||
{
|
||||
pthread_cancel(thread);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int elev_init(void)
|
||||
{
|
||||
memset(callbacks_g, 0, sizeof(callbacks_g));
|
||||
|
||||
return io_init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *polling_thread(void *p)
|
||||
{
|
||||
// Store previous values of inputs, raise signal if changed between
|
||||
// two polls.
|
||||
static int prev_values[N_FLOORS][N_SIGNALS];
|
||||
|
||||
memset(prev_values, 0, sizeof(prev_values));
|
||||
|
||||
while (1) {
|
||||
for (int type = 0; type < N_SIGNALS; type++){
|
||||
for (int floor = 0; floor < N_FLOORS; floor++){
|
||||
int value = io_read_bit(signal_channel_matrix[floor][type]);
|
||||
|
||||
// If no associated callback: ignore.
|
||||
if (callbacks_g[type] == NULL) {
|
||||
;
|
||||
}
|
||||
// If value has not changed, ignore.
|
||||
else if (value == prev_values[floor][type]) {
|
||||
;
|
||||
}
|
||||
// Obstruction is raised on any edge, with new value as param.
|
||||
else if (type == SIGNAL_TYPE_OBSTR) {
|
||||
callbacks_g[type](0, value);
|
||||
}
|
||||
// STOP is called with no arguments, only when pushed (not when
|
||||
// released).
|
||||
else if (type == SIGNAL_TYPE_STOP && value == 1) {
|
||||
callbacks_g[type](0, 0);
|
||||
}
|
||||
// Floor sensor is raised on any edge, entering and leaving floor,
|
||||
// with floor and value (edge) as param.
|
||||
else if (type == SIGNAL_TYPE_SENSOR) {
|
||||
callbacks_g[type](floor, value);
|
||||
}
|
||||
// Other signals (CALL_UP, CALL_DOWN, COMMAND) are raised on
|
||||
// rising edge only, with floor and type as parameters.
|
||||
else if (value == 1) {
|
||||
callbacks_g[type](floor, type);
|
||||
}
|
||||
// Store current value of signal to avoid multiple calls on the
|
||||
// same signal.
|
||||
prev_values[floor][type] = value;
|
||||
|
||||
// Obstr and stop is not floor dependent, so only loop once.
|
||||
if (type == SIGNAL_TYPE_OBSTR || type == SIGNAL_TYPE_STOP)
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
usleep(POLLING_INTERVAL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int elev_enable_callbacks(void)
|
||||
{
|
||||
pthread_t new_thread ;
|
||||
|
||||
if (pthread_create(&new_thread, NULL, polling_thread, NULL) != 0)
|
||||
return -1;
|
||||
else
|
||||
return new_thread;
|
||||
}
|
||||
|
||||
|
||||
void elev_reset_all_lamps(void) {
|
||||
elev_set_speed(0);
|
||||
elev_set_stop_lamp(0);
|
||||
elev_set_door_open_lamp(0);
|
||||
|
||||
for (int floor = 0; floor < N_FLOORS; ++floor) {
|
||||
elev_set_button_lamp(ELEV_DIR_DOWN, floor, 0);
|
||||
elev_set_button_lamp(ELEV_DIR_UP, floor, 0);
|
||||
elev_set_button_lamp(ELEV_DIR_COMMAND, floor, 0);
|
||||
}
|
||||
}
|
||||
|
||||
1
elev-threaded/elev.d
Executable file
1
elev-threaded/elev.d
Executable file
@ -0,0 +1 @@
|
||||
elev.o: elev.c channels.h elev.h io.h
|
||||
144
elev-threaded/elev.h
Executable file
144
elev-threaded/elev.h
Executable file
@ -0,0 +1,144 @@
|
||||
// Wrapper for libComedi Elevator control.
|
||||
// These functions provides an interface to the elevators in the real time lab
|
||||
//
|
||||
// 2006, Martin Korsgaard
|
||||
#ifndef __INCLUDE_DRIVER_ELEV_H__
|
||||
#define __INCLUDE_DRIVER_ELEV_H__
|
||||
|
||||
|
||||
// Number of floors
|
||||
#define N_FLOORS 4
|
||||
|
||||
|
||||
typedef enum elev_direction_t {ELEV_DIR_UP = 0, ELEV_DIR_DOWN = 1, ELEV_DIR_COMMAND = 2, ELEV_DIR_NONE = 2}
|
||||
elev_direction_t;
|
||||
|
||||
/**
|
||||
Sets the speed of the elevator.
|
||||
@param speed New speed of elevator. Positive values denote upward movement
|
||||
and vice versa. Set speed to 0 to stop the elevator.
|
||||
*/
|
||||
void elev_set_speed(int speed);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Turn door-open lamp on or off.
|
||||
@param value Non-zero value turns lamp on, 0 turns lamp off.
|
||||
*/
|
||||
void elev_set_door_open_lamp(int value);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Turn stop lamp on or off.
|
||||
@param value Non-zero value turns lamp on, 0 turns lamp off.
|
||||
*/
|
||||
void elev_set_stop_lamp(int value);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Set floor indicator lamp for a given floor.
|
||||
@param floor Which floor lamp to turn on. Other floor lamps are turned off.
|
||||
*/
|
||||
void elev_set_floor_indicator(int floor);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Set a button lamp.
|
||||
@param lamp Which type of lamp to set (call up, call down, or "inside"
|
||||
command).
|
||||
@param floor Floor of lamp to set.
|
||||
@param value Non-zero value turns lamp on, 0 turns lamp off.
|
||||
*/
|
||||
void elev_set_button_lamp(elev_direction_t lamp, int floor, int value);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Signal type definitions for register_callback().
|
||||
*/
|
||||
typedef enum tag_elev_signal {
|
||||
SIGNAL_TYPE_CALL_UP = 0,
|
||||
SIGNAL_TYPE_CALL_DOWN = 1,
|
||||
SIGNAL_TYPE_COMMAND = 2,
|
||||
SIGNAL_TYPE_SENSOR = 3,
|
||||
SIGNAL_TYPE_STOP = 4,
|
||||
SIGNAL_TYPE_OBSTR = 5
|
||||
} elev_signal_t;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Register a callback function to handle signals from the elevator.
|
||||
@param type Type of signal to register handler for.
|
||||
@param Callback function to call when signal arrives. The callback function
|
||||
must be on the following form: `void fun(int floor, int value)'.
|
||||
SIGNAL_TYPE_STOP triggers on pushing the stop button, `floor' and
|
||||
`value' is always passed 0.
|
||||
SIGNAL_TYPE_OBSTR triggers on flipping the obstruction switch. `floor'
|
||||
is always passed 0. `value' is one for obstruction enabled, 0 for
|
||||
disabled.
|
||||
SIGNAL_TYPE_SENSOR triggers on both entering and leaving a floor.
|
||||
`floor' is the number of the floor, `value' is 1 for entering the
|
||||
floor, 0 for leaving.
|
||||
SIGNAL_TYPE_CALL_UP,
|
||||
SIGNAL_TYPE_CALL_DOWN,
|
||||
SIGNAL_TYPE_COMMAND triggers on button push. The command buttons are the
|
||||
floor buttons "inside" the elevator. `floor' is the floor of the
|
||||
button being pushed, `value' is the type of button, according to
|
||||
elev_direction_t, defined above (ELEV_DIR_DOWN etc.).
|
||||
*/
|
||||
void elev_register_callback(elev_signal_t type, void (*callback)(int, int));
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Remove an association from a callback function.
|
||||
After calling this function, callback will not be called when the associated
|
||||
signal arrives.
|
||||
@param type Type of signal to register handler for.
|
||||
*/
|
||||
void elev_unregister_callback(elev_signal_t type);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Initialize elevator.
|
||||
@return Non-zero on success, 0 on failure.
|
||||
*/
|
||||
int elev_init(void);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Start calling callbacks when signals arrive.
|
||||
This function spawns a new thread that polls the elevator for signals (like
|
||||
the elevator arriving at a new floor, or a button is pushed), and calls
|
||||
the associated callback functions (if registered).
|
||||
@return thread index of new thread. Needed to call elev_disable_callbacks().
|
||||
*/
|
||||
int elev_enable_callbacks(void);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Stops calling callbacks when signals arrive.
|
||||
This function will kill off the thread that polls the elevator for signals.
|
||||
@param thread Value returned from corresponding elev_enable_callbacks().
|
||||
*/
|
||||
void elev_disable_callbacks(int thread) ;
|
||||
|
||||
|
||||
/**
|
||||
Clears all lamps.
|
||||
Clears all lamps. Useful on reset, as lamps from previous runs may still be
|
||||
lit.
|
||||
*/
|
||||
void elev_reset_all_lamps(void);
|
||||
|
||||
|
||||
#endif // #ifndef __INCLUDE_DRIVER_ELEV_H__
|
||||
|
||||
BIN
elev-threaded/elev.o
Executable file
BIN
elev-threaded/elev.o
Executable file
Binary file not shown.
24
elev-threaded/globals.h
Executable file
24
elev-threaded/globals.h
Executable file
@ -0,0 +1,24 @@
|
||||
#ifndef __INCLUDE_GLOBALS_H__
|
||||
#define __INCLUDE_GLOBALS_H__
|
||||
|
||||
|
||||
#define ELEV_GAIN 200
|
||||
|
||||
#define PORT 20202
|
||||
#define PORTSTR "20202"
|
||||
#define IPGROUP "129.241.187.255"
|
||||
#define TCP_LISTEN_TIMEOUT 2
|
||||
#define TCP_PING_INTERVAL 1
|
||||
#define PING_ATTEMPTS 3
|
||||
#define MAX_ELEV 10
|
||||
|
||||
// Flags for network communication
|
||||
#define PING 1
|
||||
#define PONG 2
|
||||
#define ORDER 3
|
||||
#define REQUEST 4
|
||||
#define STATUS 5
|
||||
#define CANDIDATE 6
|
||||
|
||||
|
||||
#endif
|
||||
BIN
elev-threaded/heis
Executable file
BIN
elev-threaded/heis
Executable file
Binary file not shown.
BIN
elev-threaded/heisdoc.odt
Executable file
BIN
elev-threaded/heisdoc.odt
Executable file
Binary file not shown.
BIN
elev-threaded/heisdoc.pdf
Executable file
BIN
elev-threaded/heisdoc.pdf
Executable file
Binary file not shown.
81
elev-threaded/io.c
Executable file
81
elev-threaded/io.c
Executable file
@ -0,0 +1,81 @@
|
||||
// Wrapper for libComedi I/O.
|
||||
// These functions provide and interface to libComedi limited to use in
|
||||
// the real time lab.
|
||||
//
|
||||
// 2006, Martin Korsgaard
|
||||
#include <comedilib.h>
|
||||
#include "io.h"
|
||||
#include "channels.h"
|
||||
|
||||
|
||||
// Pointer to libComedi device.
|
||||
static comedi_t *it_g = NULL;
|
||||
|
||||
|
||||
|
||||
int io_init()
|
||||
{
|
||||
int i, status = 0;
|
||||
|
||||
it_g = comedi_open("/dev/comedi0");
|
||||
|
||||
if (it_g == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
// comedi_dio_config is supposed to return 1 on success and -1 on error,
|
||||
// but seems to return 0 on success on newest versions. Anyway, do a
|
||||
// bitwise or, so that a single -1 will result in final value of -1.
|
||||
status |= comedi_dio_config(it_g, PORT1, i, COMEDI_INPUT);
|
||||
status |= comedi_dio_config(it_g, PORT2, i, COMEDI_OUTPUT);
|
||||
status |= comedi_dio_config(it_g, PORT3, i+8, COMEDI_OUTPUT);
|
||||
status |= comedi_dio_config(it_g, PORT4, i+16, COMEDI_INPUT);
|
||||
}
|
||||
|
||||
return (status != -1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void io_set_bit(int channel)
|
||||
{
|
||||
comedi_dio_write(it_g, channel >> 8, channel & 0xff, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void io_clear_bit(int channel)
|
||||
{
|
||||
comedi_dio_write(it_g, channel >> 8, channel & 0xff, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void io_write_analog(int channel, int value)
|
||||
{
|
||||
comedi_data_write(it_g, channel>>8, channel&0xff, 0, AREF_GROUND, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int io_read_bit(int channel)
|
||||
{
|
||||
unsigned int data=0;
|
||||
comedi_dio_read(it_g, channel>>8, channel&0xff, &data);
|
||||
|
||||
return (int)data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int io_read_analog(int channel)
|
||||
{
|
||||
lsampl_t data = 0;
|
||||
comedi_data_read(it_g, channel>>8, channel&0xff, 0, AREF_GROUND, &data);
|
||||
|
||||
return (int)data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
1
elev-threaded/io.d
Executable file
1
elev-threaded/io.d
Executable file
@ -0,0 +1 @@
|
||||
io.o: io.c io.h channels.h
|
||||
62
elev-threaded/io.h
Executable file
62
elev-threaded/io.h
Executable file
@ -0,0 +1,62 @@
|
||||
// Wrapper for libComedi I/O.
|
||||
// These functions provide and interface to libComedi limited to use in
|
||||
// the real time lab.
|
||||
//
|
||||
// 2006, Martin Korsgaard
|
||||
#ifndef __INCLUDE_DRIVER_IO_H__
|
||||
#define __INCLUDE_DRIVER_IO_H__
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Initialize libComedi in "Sanntidssalen"
|
||||
@return Non-zero on success and 0 on failure
|
||||
*/
|
||||
int io_init();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Sets a digital channel bit.
|
||||
@param channel Channel bit to set.
|
||||
*/
|
||||
void io_set_bit(int channel);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Clears a digital channel bit.
|
||||
@param channel Channel bit to set.
|
||||
*/
|
||||
void io_clear_bit(int channel);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Writes a value to an analog channel.
|
||||
@param channel Channel to write to.
|
||||
@param value Value to write.
|
||||
*/
|
||||
void io_write_analog(int channel, int value);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Reads a bit value from a digital channel.
|
||||
@param channel Channel to read from.
|
||||
@return Value read.
|
||||
*/
|
||||
int io_read_bit(int channel);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Reads a bit value from an analog channel.
|
||||
@param channel Channel to read from.
|
||||
@return Value read.
|
||||
*/
|
||||
int io_read_analog(int channel);
|
||||
|
||||
#endif // #ifndef __INCLUDE_DRIVER_IO_H__
|
||||
|
||||
BIN
elev-threaded/io.o
Executable file
BIN
elev-threaded/io.o
Executable file
Binary file not shown.
197
elev-threaded/local_queue.c
Executable file
197
elev-threaded/local_queue.c
Executable file
@ -0,0 +1,197 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "local_queue.h"
|
||||
#include "localsys.h"
|
||||
|
||||
|
||||
|
||||
typedef struct tag_queue {
|
||||
elev_direction_t button;
|
||||
int floor;
|
||||
struct tag_queue *next;
|
||||
} queue_t;
|
||||
|
||||
queue_t *head = NULL;
|
||||
queue_t *last = NULL;
|
||||
|
||||
|
||||
|
||||
void print_queue(){
|
||||
queue_t *it = head;
|
||||
printf("Local queue: ");
|
||||
while(it != NULL){
|
||||
printf("floor %d, type %d | ",it->floor+1, it->button);
|
||||
it = it->next;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void move_to_front(queue_t *node){
|
||||
if (node == head) return;
|
||||
|
||||
queue_t *prev = head;
|
||||
queue_t *it = head->next;
|
||||
|
||||
while (it != NULL) {
|
||||
if (it != node) continue;
|
||||
|
||||
if(prev->next == last) {
|
||||
prev->next = NULL;
|
||||
last->next = head;
|
||||
head = last;
|
||||
last = prev;
|
||||
return;
|
||||
}
|
||||
else if(prev->next == it){
|
||||
prev->next = it->next;
|
||||
it->next = head;
|
||||
head = it;
|
||||
it = prev;
|
||||
return;
|
||||
}
|
||||
it = it->next;
|
||||
prev = prev->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void passing_by(queue_t *node) {
|
||||
int end_dest = get_end_dest();
|
||||
int floor = get_floor();
|
||||
int dir = end_dest-floor;
|
||||
|
||||
if (dir > 0) {
|
||||
if ((node->floor < end_dest) && (node->floor > floor) && (node->button != ELEV_DIR_DOWN)) {
|
||||
move_to_front(node);
|
||||
set_dest(node->floor);
|
||||
printf("New destination: %d\n", node->floor+1);
|
||||
}
|
||||
}
|
||||
else if (dir < 0) {
|
||||
if ((node->floor > end_dest) && (node->floor < floor) && (node->button != ELEV_DIR_UP)) {
|
||||
move_to_front(node);
|
||||
set_dest(node->floor);
|
||||
printf("New destination: %d\n", node->floor+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void find_end_dest() {
|
||||
queue_t *it = head;
|
||||
int dest = get_dest();
|
||||
int floor = get_floor();
|
||||
int dir = dest-floor;
|
||||
|
||||
while (it != NULL) {
|
||||
if (((dir > 0) && (it->floor > get_end_dest()) && (it->button != ELEV_DIR_DOWN)) ||
|
||||
((dir < 0) && (it->floor < get_end_dest()) && (it->button != ELEV_DIR_UP))) {
|
||||
set_end_dest(it->floor);
|
||||
}
|
||||
it = it->next;
|
||||
}
|
||||
printf("End destination: %d\n", get_end_dest()+1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pop_order() {
|
||||
if(head == NULL) return;
|
||||
elev_set_button_lamp(head->button, head->floor, 0);
|
||||
|
||||
queue_t *new_head = head->next;
|
||||
free(head);
|
||||
head = new_head;
|
||||
|
||||
if(head == NULL) {
|
||||
set_dest(-1);
|
||||
set_end_dest(-1);
|
||||
last = NULL;
|
||||
}
|
||||
else {
|
||||
set_dest(head->floor);
|
||||
printf("Next destination: %d\n", head->floor+1);
|
||||
set_end_dest(head->floor);
|
||||
find_end_dest();
|
||||
}
|
||||
print_queue();
|
||||
}
|
||||
|
||||
|
||||
void add_to_queue(elev_direction_t b, int f){
|
||||
queue_t *it = head;
|
||||
while (it != NULL) {
|
||||
if ((it->button == b) && (it->floor == f)) return;
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
queue_t *new_order;
|
||||
new_order = malloc(sizeof(queue_t));
|
||||
new_order->button = b;
|
||||
new_order->floor = f;
|
||||
new_order->next = NULL;
|
||||
|
||||
if (head == NULL){
|
||||
set_end_dest(f);
|
||||
set_dest(f);
|
||||
printf("Next destination: %d\n", f+1);
|
||||
head = new_order;
|
||||
last = new_order;
|
||||
elev_set_button_lamp(b, f, 1);
|
||||
}
|
||||
else {
|
||||
last->next = new_order;
|
||||
last = new_order;
|
||||
elev_set_button_lamp(b, f, 1);
|
||||
|
||||
passing_by(last);
|
||||
find_end_dest();
|
||||
}
|
||||
print_queue();
|
||||
}
|
||||
|
||||
void remove_orders() {
|
||||
if (head == NULL) return;
|
||||
queue_t *it = head;
|
||||
int found_call = 0;
|
||||
|
||||
int dest = get_dest();
|
||||
int floor = get_floor();
|
||||
int dir = dest-floor;
|
||||
while(it != NULL){
|
||||
if (floor == it->floor) {
|
||||
if (((dir > 0) && (it->button != ELEV_DIR_DOWN)) ||
|
||||
((dir < 0) && (it->button != ELEV_DIR_UP))) {
|
||||
move_to_front(it);
|
||||
pop_order();
|
||||
}
|
||||
else if (it->button == ELEV_DIR_COMMAND) {
|
||||
move_to_front(it);
|
||||
pop_order();
|
||||
it = it->next;
|
||||
continue;
|
||||
}
|
||||
else if ((dir == 0) && (!found_call)) {
|
||||
found_call = 1;
|
||||
move_to_front(it);
|
||||
pop_order();
|
||||
}
|
||||
}
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_queue() {
|
||||
queue_t *it = head;
|
||||
while (it != NULL) {
|
||||
pop_order();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
elev-threaded/local_queue.d
Executable file
1
elev-threaded/local_queue.d
Executable file
@ -0,0 +1 @@
|
||||
local_queue.o: local_queue.c local_queue.h elev.h localsys.h
|
||||
6
elev-threaded/local_queue.h
Executable file
6
elev-threaded/local_queue.h
Executable file
@ -0,0 +1,6 @@
|
||||
#include "elev.h"
|
||||
|
||||
void add_to_queue(elev_direction_t b, int f);
|
||||
void clear_queue();
|
||||
void remove_orders();
|
||||
int get_head();
|
||||
BIN
elev-threaded/local_queue.o
Executable file
BIN
elev-threaded/local_queue.o
Executable file
Binary file not shown.
297
elev-threaded/localsys.c
Executable file
297
elev-threaded/localsys.c
Executable file
@ -0,0 +1,297 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "local_queue.h"
|
||||
#include "elev.h"
|
||||
#include "io.h"
|
||||
#include "channels.h"
|
||||
#include "globals.h"
|
||||
#include "localsys.h"
|
||||
#include "netmod.h"
|
||||
#include "mastermod.h"
|
||||
|
||||
|
||||
int dest = -1;
|
||||
int end_dest = -1;
|
||||
elev_state_t state;
|
||||
int current_floor = -1;
|
||||
char msg[BUFLEN_TCP];
|
||||
|
||||
|
||||
void set_dest(int f) {
|
||||
dest = f;
|
||||
}
|
||||
int get_dest() {
|
||||
return dest;
|
||||
}
|
||||
|
||||
void set_end_dest(int f) {
|
||||
end_dest = f;
|
||||
}
|
||||
|
||||
int get_end_dest() {
|
||||
return end_dest;
|
||||
}
|
||||
|
||||
int get_state() {
|
||||
return state;
|
||||
}
|
||||
|
||||
int get_floor() {
|
||||
return current_floor;
|
||||
}
|
||||
|
||||
void status_str(int s, int f, int end) {
|
||||
msg[0] = (char) STATUS;
|
||||
msg[1] = (char) s;
|
||||
msg[2] = (char) f;
|
||||
msg[3] = (char) end;
|
||||
}
|
||||
|
||||
int timeDelay(int sec) {
|
||||
static int count;
|
||||
static time_t start;
|
||||
count ++;
|
||||
if ( count == 1) {
|
||||
time(&start);
|
||||
}
|
||||
time_t end;
|
||||
time(&end);
|
||||
|
||||
if (difftime(end,start) >= sec) {
|
||||
count = 0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* state_machine(){
|
||||
while(1) {
|
||||
switch (state) {
|
||||
|
||||
case DOOROPEN:
|
||||
elev_set_door_open_lamp(1);
|
||||
if (io_read_bit(OBSTRUCTION)) break;
|
||||
|
||||
if (timeDelay(3)) {
|
||||
state = DOORCLOSED;
|
||||
elev_set_door_open_lamp(0);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
usleep(1e4);
|
||||
break;
|
||||
}
|
||||
|
||||
case DOORCLOSED:
|
||||
if (dest < 0){
|
||||
printf("State: IDLE\n");
|
||||
state = IDLE;
|
||||
status_str(state, current_floor, end_dest);
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
else if (current_floor < dest){
|
||||
elev_set_speed(150);
|
||||
printf("State: MOVING_UP\n");
|
||||
state = MOVING_UP;
|
||||
status_str(state, current_floor, end_dest);
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
else if (current_floor > dest) {
|
||||
elev_set_speed(-150);
|
||||
printf("State: MOVING_DOWN\n");
|
||||
state = MOVING_DOWN;
|
||||
status_str(state, current_floor, end_dest);
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
else if (current_floor == dest){
|
||||
remove_orders();
|
||||
printf("State: DOOROPEN\n");
|
||||
state = DOOROPEN;
|
||||
break;
|
||||
}
|
||||
|
||||
case IDLE:
|
||||
if (dest > -1) {
|
||||
state = DOORCLOSED;
|
||||
status_str(state, current_floor, end_dest);
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
}
|
||||
usleep(1e4);
|
||||
|
||||
default:
|
||||
usleep(1e4);
|
||||
|
||||
}
|
||||
usleep(100);
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void stop_func(int floor, int value) {
|
||||
elev_set_speed(0);
|
||||
elev_set_stop_lamp(1);
|
||||
state = STOPPED;
|
||||
status_str(state, current_floor, end_dest);
|
||||
printf("STOPPED\n");
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
|
||||
}
|
||||
|
||||
void command_func(int floor, int value) {
|
||||
if (state == STOPPED) {
|
||||
elev_set_speed(ELEV_GAIN);
|
||||
elev_set_stop_lamp(0);
|
||||
}
|
||||
|
||||
add_to_queue(value, floor);
|
||||
}
|
||||
|
||||
void elev_order_func(int floor, int value) {
|
||||
char send[BUFLEN_TCP];
|
||||
if (get_role() != MASTER) {
|
||||
// Make backup? Check with ping pong etc
|
||||
send[0] = (char) ORDER;
|
||||
send[1] = (char) value;
|
||||
send[2] = (char) floor;
|
||||
|
||||
if (tcp_write(get_master_sock(), send) == -1) printf("Cant write to master, do something something...\n");
|
||||
|
||||
}
|
||||
else {
|
||||
int elev = find_opt_elev(value, floor);
|
||||
printf("Optimal elevator has socketid %d\n", elev);
|
||||
|
||||
if (elev != -1) {
|
||||
send[0] = (char) REQUEST;
|
||||
if (tcp_write(elev, send) == -1) printf("Failed to give order...\n");
|
||||
}
|
||||
else add_to_queue(value, floor);
|
||||
}
|
||||
}
|
||||
|
||||
void sensor_func(int floor, int value) {
|
||||
if (value == 0) return;
|
||||
|
||||
elev_set_floor_indicator(floor);
|
||||
current_floor = floor;
|
||||
printf("Current floor: %d\n", current_floor+1);
|
||||
|
||||
if (floor == dest) {
|
||||
printf("Arriving at floor %d\n", floor+1);
|
||||
elev_set_speed(0);
|
||||
remove_orders();
|
||||
//Husk å fjerne alle aktuelle ordre ved en funksjon
|
||||
state = DOOROPEN;
|
||||
status_str(state, current_floor, end_dest);
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
printf("State: DOOROPEN\n");
|
||||
return;
|
||||
}
|
||||
if ((current_floor == N_FLOORS-1) || (current_floor == 0)) {
|
||||
printf("Reached end of shaft unexpectedly\n");
|
||||
elev_set_speed(0);
|
||||
state = DOOROPEN;
|
||||
status_str(state, current_floor, end_dest);
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
printf("State: DOOROPEN\n");
|
||||
}
|
||||
}
|
||||
|
||||
void sensor_func_init(int floor, int value) {
|
||||
elev_set_speed(0);
|
||||
current_floor = floor;
|
||||
elev_unregister_callback(SIGNAL_TYPE_SENSOR);
|
||||
elev_register_callback(SIGNAL_TYPE_SENSOR, &sensor_func);
|
||||
elev_register_callback(SIGNAL_TYPE_COMMAND, &command_func);
|
||||
elev_register_callback(SIGNAL_TYPE_CALL_UP, &elev_order_func);
|
||||
elev_register_callback(SIGNAL_TYPE_CALL_DOWN, &elev_order_func);
|
||||
elev_register_callback(SIGNAL_TYPE_STOP, &stop_func);
|
||||
state = IDLE;
|
||||
pthread_t state_th;
|
||||
pthread_create(&state_th, NULL, state_machine, NULL);
|
||||
printf("Elevator initialized and ready for use.\n");
|
||||
|
||||
status_str(state, current_floor, end_dest);
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
}
|
||||
|
||||
int localsys_init() {
|
||||
|
||||
if (!elev_init()) {
|
||||
printf(__FILE__ ": Unable to initialize elevator hardware\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
elev_reset_all_lamps();
|
||||
clear_queue();
|
||||
|
||||
if (io_read_bit(SENSOR1)) current_floor = 0;
|
||||
if (io_read_bit(SENSOR2)) current_floor = 1;
|
||||
if (io_read_bit(SENSOR3)) current_floor = 2;
|
||||
if (io_read_bit(SENSOR4)) current_floor = 3;
|
||||
|
||||
if (current_floor > 0) {
|
||||
elev_register_callback(SIGNAL_TYPE_SENSOR, &sensor_func);
|
||||
elev_register_callback(SIGNAL_TYPE_COMMAND, &command_func);
|
||||
elev_register_callback(SIGNAL_TYPE_CALL_UP, &elev_order_func);
|
||||
elev_register_callback(SIGNAL_TYPE_CALL_DOWN, &elev_order_func);
|
||||
elev_register_callback(SIGNAL_TYPE_STOP, &stop_func);
|
||||
state = IDLE;
|
||||
pthread_t state_th;
|
||||
pthread_create(&state_th, NULL, state_machine, NULL);
|
||||
printf("Elevator initialized and ready for use.\n");
|
||||
|
||||
status_str(state, current_floor, end_dest);
|
||||
if (get_role() != MASTER) {
|
||||
if (write(get_master_sock(), msg, BUFLEN_TCP) == -1) printf("Failed to send status\n");
|
||||
}
|
||||
else set_elev_state(-1, msg);
|
||||
}
|
||||
else {
|
||||
printf("Going to nearest floor...\n");
|
||||
elev_register_callback(SIGNAL_TYPE_SENSOR, &sensor_func_init);
|
||||
elev_set_speed(-ELEV_GAIN);
|
||||
}
|
||||
|
||||
int callback_th = elev_enable_callbacks();
|
||||
return callback_th;
|
||||
}
|
||||
|
||||
|
||||
2
elev-threaded/localsys.d
Executable file
2
elev-threaded/localsys.d
Executable file
@ -0,0 +1,2 @@
|
||||
localsys.o: localsys.c local_queue.h elev.h io.h channels.h globals.h \
|
||||
localsys.h netmod.h mastermod.h
|
||||
19
elev-threaded/localsys.h
Executable file
19
elev-threaded/localsys.h
Executable file
@ -0,0 +1,19 @@
|
||||
typedef enum tag_elev_state {
|
||||
DOOROPEN = 0,
|
||||
MOVING_UP = 1,
|
||||
MOVING_DOWN = 2,
|
||||
DOORCLOSED = 3,
|
||||
STOPPED = 4,
|
||||
IDLE = 5,
|
||||
} elev_state_t;
|
||||
|
||||
|
||||
void set_dest(int f);
|
||||
int get_dest();
|
||||
void set_end_dest(int f);
|
||||
int get_end_dest();
|
||||
int get_state();
|
||||
int get_floor();
|
||||
int localsys_init();
|
||||
int timeDelay(int sec);
|
||||
|
||||
BIN
elev-threaded/localsys.o
Executable file
BIN
elev-threaded/localsys.o
Executable file
Binary file not shown.
37
elev-threaded/main.c
Executable file
37
elev-threaded/main.c
Executable file
@ -0,0 +1,37 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
//#include "elev.h"
|
||||
#include "localsys.h"
|
||||
#include "netmod.h"
|
||||
#include "globals.h"
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc > 1) {
|
||||
printf("Usage: Just run 'heis' on Sanntidssalen.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\n########################################\n");
|
||||
printf("Group 20\nMichael Soukup & Petter Rossvoll\n");
|
||||
printf("########################################\n\n");
|
||||
|
||||
printf("Initializing network on subnet %s through port %d...\n", IPGROUP, PORT);
|
||||
|
||||
net_init();
|
||||
|
||||
printf("Initializing elevator...\n");
|
||||
int callback_th;
|
||||
callback_th = localsys_init();
|
||||
|
||||
|
||||
while (1) {
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
1
elev-threaded/main.d
Executable file
1
elev-threaded/main.d
Executable file
@ -0,0 +1 @@
|
||||
main.o: main.c localsys.h netmod.h globals.h
|
||||
BIN
elev-threaded/main.o
Executable file
BIN
elev-threaded/main.o
Executable file
Binary file not shown.
201
elev-threaded/mastermod.c
Executable file
201
elev-threaded/mastermod.c
Executable file
@ -0,0 +1,201 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "localsys.h"
|
||||
#include "mastermod.h"
|
||||
#include "elev.h"
|
||||
#include "globals.h"
|
||||
#include "netmod.h"
|
||||
|
||||
|
||||
role_t role = MASTER;
|
||||
int master_sock;
|
||||
int master_cand_sock = -1;
|
||||
status_t *lhead = NULL;
|
||||
status_t *llast = NULL;
|
||||
|
||||
|
||||
void print_status(){
|
||||
status_t *it = lhead;
|
||||
printf("Online Elevators: ");
|
||||
while(it != NULL){
|
||||
printf("socket %d, role %d | ",it->sockid, it->role);
|
||||
it = it->next;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void add_to_list(int sock){
|
||||
status_t *new_elev;
|
||||
new_elev = malloc(sizeof(status_t));
|
||||
new_elev->sockid = sock;
|
||||
new_elev->next = NULL;
|
||||
|
||||
if (lhead == NULL){
|
||||
lhead = new_elev;
|
||||
}
|
||||
else {
|
||||
llast->next = new_elev;
|
||||
}
|
||||
llast = new_elev;
|
||||
print_status();
|
||||
}
|
||||
|
||||
int get_master_cand_sock() {
|
||||
return master_cand_sock;
|
||||
}
|
||||
|
||||
void set_alive(int sock, int b) {
|
||||
status_t *it = lhead;
|
||||
while(it != NULL){
|
||||
if (it->sockid == sock) {
|
||||
it->alive = b;
|
||||
return;
|
||||
}
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
role_t get_role() {
|
||||
return role;
|
||||
}
|
||||
void set_role(role_t r) {
|
||||
role = r;
|
||||
}
|
||||
|
||||
int get_master_sock() {
|
||||
return master_sock;
|
||||
}
|
||||
|
||||
void set_master_flag() {
|
||||
lhead->sockid = -1;
|
||||
}
|
||||
|
||||
void set_master_sock(int sock) {
|
||||
master_sock = sock;
|
||||
}
|
||||
|
||||
void print_elevs() {
|
||||
status_t *it = lhead;
|
||||
printf("Elevator list: ");
|
||||
while(it != NULL){
|
||||
printf("Socket %d, alive %d\n",it->sockid, it->alive);
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
void add_elev(int sock){
|
||||
status_t *new_elev;
|
||||
new_elev = malloc(sizeof(status_t));
|
||||
new_elev->sockid = sock;
|
||||
new_elev->floor = 0;
|
||||
new_elev->end_dest = 0;
|
||||
new_elev->state = STOPPED;
|
||||
new_elev->alive = 1;
|
||||
new_elev->next = NULL;
|
||||
|
||||
if (lhead == NULL){
|
||||
lhead = new_elev;
|
||||
new_elev->role = MASTER;
|
||||
}
|
||||
else {
|
||||
llast->next = new_elev;
|
||||
new_elev->role = SLAVE;
|
||||
}
|
||||
llast = new_elev;
|
||||
print_elevs();
|
||||
}
|
||||
|
||||
void master_init(int s) {
|
||||
add_elev(s);
|
||||
lhead->role = MASTER;
|
||||
lhead->alive = 1;
|
||||
}
|
||||
|
||||
void add_slave(int sock) {
|
||||
add_to_list(sock);
|
||||
|
||||
llast->floor = 0;
|
||||
llast->state = STOPPED;
|
||||
llast->alive = 1;
|
||||
llast->end_dest = 0;
|
||||
|
||||
if (master_cand_sock == -1) {
|
||||
master_cand_sock = sock;
|
||||
llast->role = MASTER_CAND;
|
||||
}
|
||||
else llast->role = SLAVE;
|
||||
}
|
||||
|
||||
void set_elev_state(int sock, char str[]) {
|
||||
status_t *it = lhead;
|
||||
while(it != NULL){
|
||||
if (it->sockid == sock) {
|
||||
it->state = (int) str[1];
|
||||
it->floor = (int) str[2];
|
||||
it->end_dest = (int) str[3];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
int find_opt_elev(int call, int floor) {
|
||||
int best = abs(floor - lhead->floor);
|
||||
status_t *res = lhead;
|
||||
status_t *it = lhead->next;
|
||||
int dir = lhead->end_dest-lhead->floor;
|
||||
|
||||
int passing = 0;
|
||||
int idle = 0;
|
||||
|
||||
while (it != NULL) {
|
||||
if (((!it->alive) || (it->end_dest == -1))) {
|
||||
it = it->next;
|
||||
continue;
|
||||
}
|
||||
dir = it->end_dest-it->floor;
|
||||
|
||||
if (((dir > 0) && (floor > it->floor) && (floor <= it->end_dest) && (call != ELEV_DIR_DOWN)) ||
|
||||
((dir < 0) && (floor < it->floor) && (floor >= it->end_dest) && (call != ELEV_DIR_UP))) {
|
||||
if (abs(floor - it->floor) < best) {
|
||||
res = it;
|
||||
best = abs(floor - it->floor);
|
||||
passing = 1;
|
||||
}
|
||||
}
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
if (!passing) {
|
||||
it = lhead;
|
||||
best = N_FLOORS+1;
|
||||
while (it != NULL) {
|
||||
if (!it->alive) {
|
||||
it = it->next;
|
||||
continue;
|
||||
}
|
||||
if ((it->state == IDLE) && (abs(floor - it->floor) < best)) {
|
||||
best = abs(floor - it->floor);
|
||||
res = it;
|
||||
idle = 1;
|
||||
}
|
||||
else if ((!idle) && (abs(floor - it->floor) < best)){
|
||||
best = abs(floor - it->floor);
|
||||
res = it;
|
||||
}
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
}
|
||||
return res->sockid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1
elev-threaded/mastermod.d
Executable file
1
elev-threaded/mastermod.d
Executable file
@ -0,0 +1 @@
|
||||
mastermod.o: mastermod.c localsys.h mastermod.h elev.h globals.h netmod.h
|
||||
30
elev-threaded/mastermod.h
Executable file
30
elev-threaded/mastermod.h
Executable file
@ -0,0 +1,30 @@
|
||||
|
||||
typedef enum tag_role{
|
||||
SLAVE = 0,
|
||||
MASTER = 1,
|
||||
MASTER_CAND = 2,
|
||||
} role_t;
|
||||
|
||||
typedef struct tag_status {
|
||||
int sockid;
|
||||
int floor;
|
||||
int end_dest;
|
||||
elev_state_t state;
|
||||
role_t role;
|
||||
int alive;
|
||||
struct tag_status *next;
|
||||
} status_t;
|
||||
|
||||
int get_master_cand_sock();
|
||||
role_t get_role();
|
||||
void set_role(role_t r);
|
||||
void set_alive(int sock, int b);
|
||||
void set_master_flag();
|
||||
void set_master_sock(int sock);
|
||||
int get_master_sock();
|
||||
int get_master_cand_sock();
|
||||
void master_init();
|
||||
void add_slave(int sock);
|
||||
void set_elev_state(int sock, char str[]);
|
||||
int find_opt_elev(int call, int floor);
|
||||
|
||||
BIN
elev-threaded/mastermod.o
Executable file
BIN
elev-threaded/mastermod.o
Executable file
Binary file not shown.
360
elev-threaded/netmod.c
Executable file
360
elev-threaded/netmod.c
Executable file
@ -0,0 +1,360 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "localsys.h"
|
||||
#include "netmod.h"
|
||||
#include "local_queue.h"
|
||||
#include "globals.h"
|
||||
#include "mastermod.h"
|
||||
|
||||
|
||||
int ping_tries = 0;
|
||||
|
||||
int tcp_write(int sock, char s[]) {
|
||||
return send(sock, s, BUFLEN_TCP, 0);
|
||||
}
|
||||
|
||||
void* tcp_read(void* s) {
|
||||
int sock = (int) s;
|
||||
char rec_buf[BUFLEN_TCP];
|
||||
char sen_buf[BUFLEN_TCP];
|
||||
//char order_buf[BUFLEN_TCP];
|
||||
int flag = -1;
|
||||
int cand_isset = 0;
|
||||
int err;
|
||||
|
||||
while (1) {
|
||||
err = recv(sock, rec_buf, BUFLEN_TCP, 0);
|
||||
if (err < 0) {
|
||||
printf("Connection error recv from socket id %d\n", sock);
|
||||
if (get_role() != SLAVE) set_alive(sock, 0);
|
||||
return NULL;
|
||||
}
|
||||
else if (err == 0){
|
||||
printf("Connection with socket id %d was shut down\n", sock);
|
||||
if (get_role() != SLAVE) set_alive(sock, 0);
|
||||
return NULL;
|
||||
}
|
||||
flag = (int) rec_buf[0];
|
||||
|
||||
switch (flag) {
|
||||
case PING:
|
||||
if (!cand_isset) {
|
||||
if (sock == get_master_cand_sock()) {
|
||||
sen_buf[0] = (char) CANDIDATE;
|
||||
sen_buf[1] = (char) 1;
|
||||
cand_isset = 1;
|
||||
if (write(sock, sen_buf, BUFLEN_TCP) == -1) printf("Couldnt set candidate!\n");
|
||||
}
|
||||
else {
|
||||
sen_buf[0] = (char) CANDIDATE;
|
||||
sen_buf[1] = (char) 0;
|
||||
if (write(sock, sen_buf, BUFLEN_TCP) == -1) printf("Couldnt set candidate!\n");
|
||||
cand_isset = 1;
|
||||
}
|
||||
}
|
||||
sen_buf[0] = (char) PONG;
|
||||
write(sock, sen_buf, BUFLEN_TCP);
|
||||
break;
|
||||
|
||||
case PONG:
|
||||
ping_tries = 0;
|
||||
break;
|
||||
|
||||
case STATUS:
|
||||
set_elev_state(sock, rec_buf);
|
||||
printf("Status update: state %d, floor %d, end destination %d\n", rec_buf[1], rec_buf[2], rec_buf[3]);
|
||||
|
||||
break;
|
||||
|
||||
case ORDER:
|
||||
printf("New order. Call %d, floor %d\n", rec_buf[1], rec_buf[2]);
|
||||
/*order_buf[0] = (char) ORDER;
|
||||
order_buf[1] = rec_buf[1];
|
||||
order_buf[2] = rec_buf[2];*/
|
||||
sen_buf[0] = (char) REQUEST;
|
||||
sen_buf[1] = (char) rec_buf[1];
|
||||
sen_buf[2] = (char) rec_buf[2];
|
||||
|
||||
int elev = find_opt_elev((int) rec_buf[1], (int) rec_buf[2]);
|
||||
printf("Optimal elevator has socketid %d\n", elev);
|
||||
|
||||
if (elev != -1) {
|
||||
if (write(elev, sen_buf, BUFLEN_TCP) == -1) printf("Couldnt deliver order!\n");
|
||||
}
|
||||
else add_to_queue((int) rec_buf[1], (int) rec_buf[2]);
|
||||
break;
|
||||
|
||||
case REQUEST:
|
||||
elev_set_button_lamp((int) rec_buf[1], (int) rec_buf[2], 1);
|
||||
printf("New request\n");
|
||||
add_to_queue((int) rec_buf[1], (int) rec_buf[2]);
|
||||
break;
|
||||
|
||||
case CANDIDATE:
|
||||
if ((int) rec_buf[1]) {
|
||||
printf("Taking role as master candidate\n");
|
||||
master_init(sock);
|
||||
set_role(MASTER_CAND);
|
||||
}
|
||||
else {
|
||||
printf("Taking role as slave\n");
|
||||
set_role(SLAVE);
|
||||
}
|
||||
break;
|
||||
|
||||
case (-1):
|
||||
printf("Flag is not set\n");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* ping_master(void* s) {
|
||||
int socket = (int) s;
|
||||
char msg[BUFLEN_TCP];
|
||||
msg[0] = (char) PING;
|
||||
while(1) {
|
||||
//printf("-> Ping...\n");
|
||||
write(socket, msg, BUFLEN_TCP);
|
||||
if(ping_tries == PING_ATTEMPTS) {
|
||||
printf("Lost connection to master\n");
|
||||
break;
|
||||
}
|
||||
ping_tries++;
|
||||
sleep(TCP_PING_INTERVAL);
|
||||
}
|
||||
|
||||
printf("No pong response!\n");
|
||||
net_init();
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void* tcp_listen(void* timeout_id) {
|
||||
struct sockaddr_in socklisten_addr;
|
||||
struct sockaddr_in master_addr;
|
||||
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
socklen_t addrlen;
|
||||
|
||||
if (sock == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&socklisten_addr, 0, sizeof socklisten_addr);
|
||||
socklisten_addr.sin_family = AF_INET;
|
||||
socklisten_addr.sin_port = htons(PORT);
|
||||
socklisten_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
int reuse = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse) == -1) {
|
||||
perror("setsockopt");
|
||||
close(sock);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&socklisten_addr, sizeof socklisten_addr) == -1) {
|
||||
perror("bind");
|
||||
close(sock);
|
||||
//exit(1);
|
||||
}
|
||||
|
||||
if (listen(sock, 1) < 0) {
|
||||
perror("listen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Waiting to accept...\n");
|
||||
addrlen = sizeof master_addr;
|
||||
int sock_master = accept(sock, (struct sockaddr *)&master_addr, &addrlen);
|
||||
|
||||
printf("Connected to master\n");
|
||||
set_master_sock(sock_master);
|
||||
set_role(SLAVE);
|
||||
|
||||
pthread_t read_th, ping_th;
|
||||
pthread_create(&read_th, NULL, tcp_read, (void*) sock_master);
|
||||
pthread_create(&ping_th, NULL, ping_master, (void*) sock_master);
|
||||
|
||||
printf("Network initialization complete.\n");
|
||||
|
||||
close(sock);
|
||||
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void tcp_connect(char ip[]) {
|
||||
struct sockaddr_in sockconn_addr;
|
||||
int sockid = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (sockid == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&sockconn_addr, 0, sizeof sockconn_addr);
|
||||
sockconn_addr.sin_family = AF_INET;
|
||||
sockconn_addr.sin_port = htons(PORT);
|
||||
|
||||
if(inet_pton(AF_INET, ip, &sockconn_addr.sin_addr) == 0) {
|
||||
perror("Not a valid ip");
|
||||
close(sockid);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Connecting to %s ...\n", ip);
|
||||
if (connect(sockid, (struct sockaddr *)&sockconn_addr, sizeof sockconn_addr) == -1) {
|
||||
perror("connect");
|
||||
close(sockid);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Connected to slave with socket ID %d\n", sockid);
|
||||
add_slave(sockid);
|
||||
|
||||
pthread_t read_th;
|
||||
pthread_create(&read_th, NULL, tcp_read, (void*) sockid);
|
||||
}
|
||||
|
||||
void udp_broadcast() {
|
||||
int sock;
|
||||
struct sockaddr_in broadcast_addr;
|
||||
struct hostent *he;
|
||||
int broadcast = 1;
|
||||
|
||||
char dummymsg[BUFLEN_UDP] = "\0";
|
||||
|
||||
if ((he = gethostbyname(IPGROUP)) == NULL) {
|
||||
perror("gethostbyname");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Allow broadcast
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast) == -1) {
|
||||
perror("setsockopt (SO_BROADCAST)");
|
||||
close(sock);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
broadcast_addr.sin_family = AF_INET;
|
||||
broadcast_addr.sin_port = htons(PORT);
|
||||
broadcast_addr.sin_addr = *((struct in_addr *)he->h_addr);
|
||||
memset(broadcast_addr.sin_zero, '\0', sizeof broadcast_addr.sin_zero);
|
||||
|
||||
|
||||
printf("Broadcasting to %s\n", IPGROUP);
|
||||
if (sendto(sock, dummymsg, strlen(dummymsg), 0, (struct sockaddr *)&broadcast_addr, sizeof broadcast_addr) == -1) {
|
||||
perror("sendto");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void* udp_listen() {
|
||||
int sock;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp;
|
||||
struct sockaddr_in slave_addr;
|
||||
char buf[BUFLEN_UDP];
|
||||
socklen_t addrlen = sizeof(struct sockaddr);
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
if (getaddrinfo(NULL, PORTSTR, &hints, &result) != 0) {
|
||||
perror("getaddrinfo");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
sock = socket(rp->ai_family, rp->ai_socktype, 0);
|
||||
|
||||
if (sock == -1)
|
||||
continue;
|
||||
|
||||
if (bind(sock, rp->ai_addr, rp->ai_addrlen) == 0)
|
||||
break;
|
||||
|
||||
close(sock);
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
printf("Waiting for slaves...\n");
|
||||
|
||||
while(1) {
|
||||
|
||||
if (recvfrom(sock, buf, BUFLEN_UDP, 0, (struct sockaddr *)&slave_addr, &addrlen) == -1) {
|
||||
perror("recvfrom");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Found new slave\n");
|
||||
tcp_connect(inet_ntoa(slave_addr.sin_addr));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* timeout(void* tcp_listen_id) {
|
||||
sleep(TCP_LISTEN_TIMEOUT);
|
||||
|
||||
if (get_role() == MASTER) {
|
||||
printf("Master is not present\nStarting as master...\n");
|
||||
master_init(-1);
|
||||
pthread_cancel((pthread_t) tcp_listen_id);
|
||||
printf("Start listening for slave broadcasts through UDP\n");
|
||||
pthread_t udp_listen_th;
|
||||
pthread_create(&udp_listen_th, NULL, udp_listen, NULL);
|
||||
printf("Network initialization complete.\n");
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void net_init() {
|
||||
printf("Starting search for master\n");
|
||||
|
||||
if (get_role() == MASTER_CAND) {
|
||||
set_role(MASTER);
|
||||
set_master_flag();
|
||||
printf("I am master candidate. Taking role as master...\n");
|
||||
pthread_t udp_listen_th;
|
||||
pthread_create(&udp_listen_th, NULL, udp_listen, NULL);
|
||||
}
|
||||
else {
|
||||
pthread_t tcp_listen_th, timeout_th;
|
||||
pthread_create(&tcp_listen_th, NULL, tcp_listen, (void*) timeout_th);
|
||||
pthread_create(&timeout_th, NULL, timeout, (void*) tcp_listen_th);
|
||||
|
||||
udp_broadcast();
|
||||
|
||||
pthread_join(timeout_th, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
elev-threaded/netmod.d
Executable file
2
elev-threaded/netmod.d
Executable file
@ -0,0 +1,2 @@
|
||||
netmod.o: netmod.c localsys.h netmod.h local_queue.h elev.h globals.h \
|
||||
mastermod.h
|
||||
6
elev-threaded/netmod.h
Executable file
6
elev-threaded/netmod.h
Executable file
@ -0,0 +1,6 @@
|
||||
#define BUFLEN_TCP 16
|
||||
#define BUFLEN_UDP 16
|
||||
|
||||
void net_init();
|
||||
int tcp_write(int sock, char s[]);
|
||||
|
||||
BIN
elev-threaded/netmod.o
Executable file
BIN
elev-threaded/netmod.o
Executable file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user