I shall attach the .script and .urp files for the singular TCP/IP client program running on the teach pendant and have the two C++ server .cpp files as code blocks (one for the main execution, and one for the global variable value receiving).
Client:
ur5_tcp_working_plus_push_parallel.script (6.0 KB)
ur5_tcp_working_plus_push_parallel.urp (3.1 KB)
Main execution TCP/IP socket server:
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int count = 0;
std::cout << "Starting Program" << std::endl;
portno = 30000;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
std::cerr << "Error opening socket" << std::endl;
return 1;
}
int optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
std::cerr << "Error binding socket" << std::endl;
return 1;
}
std::cout << "Listening" << std::endl;
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
std::cerr << "Error accepting connection" << std::endl;
return 1;
}
std::cout << "Connected to " << inet_ntoa(cli_addr.sin_addr) << std::endl;
try {
memset(buffer, 0, sizeof(buffer));
ssize_t n = read(newsockfd, buffer, sizeof(buffer) - 1);
if (n < 0) {
std::cerr << "Error reading from socket" << std::endl;
return 1;
}
std::cout << buffer << std::endl;
count++;
std::cout << "The count is: " << count << std::endl;
usleep(500000);
std::cout << std::endl;
usleep(500000);
std::string firstMessage = "(1.1)";
ssize_t m1 = write(newsockfd, firstMessage.c_str(), firstMessage.length());
if (m1 < 0) {
std::cerr << "Error writing first message to socket" << std::endl;
return 1;
}
std::cout << "Sent 1.1" << std::endl;
std::string secondMessage = "(100.0,100.0,0.0,0.0,0.0,0.0)";
ssize_t m2 = write(newsockfd, secondMessage.c_str(), secondMessage.length());
if (m2 < 0) {
std::cerr << "Error writing second message to socket" << std::endl;
return 1;
}
std::cout << "Sent (100.0,100.0,0.0,0.0,0.0,0.0)" << std::endl;
// Wait for client to be ready
memset(buffer, 0, sizeof(buffer));
ssize_t n3 = read(newsockfd, buffer, sizeof(buffer) - 1);
if (n3 < 0) {
std::cerr << "Error reading from socket" << std::endl;
return 1;
}
std::cout << "Received acknowledgment from the client: " << buffer << std::endl;
std::string thirdMessage = "(2.2)";
ssize_t m3 = write(newsockfd, thirdMessage.c_str(), thirdMessage.length());
if (m3 < 0) {
std::cerr << "Error writing third message to socket" << std::endl;
return 1;
}
std::cout << "Sent 2.2" << std::endl;
std::string fourthMessage = "(0.0,0.0,0.0,0.0,0.0,0.0)";
ssize_t m4 = write(newsockfd, fourthMessage.c_str(), fourthMessage.length());
if (m4 < 0) {
std::cerr << "Error writing fourth message to socket" << std::endl;
return 1;
}
std::cout << "Sent (0.0,0.0,0.0,0.0,0.0,0.0)" << std::endl;
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
}
close(newsockfd);
close(sockfd);
std::cout << "Program finish" << std::endl;
return 0;
}
Global variable value receiving TCP/IP socket server:
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <chrono>
#include <ctime>
#include <thread>
#include <curl/curl.h>
// Function to send an SMS using Twilio API
void sendSMS(const std::string& accountSID, const std::string& authToken,
const std::string& fromNumber, const std::string& toNumber,
const std::string& message) {
std::string url = "https://api.twilio.com/2010-04-01/Accounts/" + accountSID +
"/Messages.json";
std::string postFields = "To=" + toNumber + "&From=" + fromNumber +
"&Body=" + curl_easy_escape(NULL, message.c_str(), 0);
CURL* curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields.c_str());
curl_easy_setopt(curl, CURLOPT_USERPWD, (accountSID + ":" + authToken).c_str());
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
std::cerr << "Failed to send SMS: " << curl_easy_strerror(res) << std::endl;
curl_easy_cleanup(curl);
}
}
int main() {
// Twilio account SID and auth token
std::string accountSID = "{account SID here}";
std::string authToken = "{account token here}";
// Phone numbers
std::string fromNumber = "{from phone number here}";
std::string toNumber = "{to phone number here}";
// Message to send
std::string message = "UR5 STOPPED!";
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
std::cout << "Starting Program" << std::endl;
portno = 30001;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
std::cerr << "Error opening socket" << std::endl;
return 1;
}
int optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
std::cerr << "Error binding socket" << std::endl;
return 1;
}
std::cout << "Listening" << std::endl;
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
std::cerr << "Error accepting connection" << std::endl;
return 1;
}
std::cout << "Connected to " << inet_ntoa(cli_addr.sin_addr) << std::endl;
try {
memset(buffer, 0, sizeof(buffer));
ssize_t n = read(newsockfd, buffer, sizeof(buffer) - 1);
if (n < 0) {
std::cerr << "Error reading from socket" << std::endl;
return 1;
}
std::cout << buffer << std::endl;
// Flag to track acknowledgment status
bool receivedAcknowledgment = true;
// Start a thread to monitor acknowledgment
std::thread acknowledgmentMonitor([&]() {
std::chrono::seconds timeout(2);
std::time_t lastAcknowledgmentTime = std::time(nullptr);
while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::time_t currentTime = std::time(nullptr);
if (currentTime - lastAcknowledgmentTime > timeout.count()) {
std::cout << "No acknowledgment received for more than 2 seconds. Sending SMS..." << std::endl;
sendSMS(accountSID, authToken, fromNumber, toNumber, message);
return 0;
break;
}
else if (receivedAcknowledgment) {
// Reset the timer if acknowledgment is received
lastAcknowledgmentTime = std::time(nullptr);
receivedAcknowledgment = false;
}
}
});
// Continuously receive acknowledgments from the client
while (receivedAcknowledgment) {
memset(buffer, 0, sizeof(buffer));
ssize_t n = read(newsockfd, buffer, sizeof(buffer) - 1);
if (n < 0) {
std::cerr << "Error reading from socket" << std::endl;
return 1;
}
std::string acknowledgment = buffer;
if (!acknowledgment.empty()) {
std::cout << "Received acknowledgment from the client: " << acknowledgment << std::endl;
receivedAcknowledgment = true;
}
}
acknowledgmentMonitor.join();
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
}
close(newsockfd);
close(sockfd);
std::cout << "Program finish" << std::endl;
return 0;
}
I would like for both servers to bind to the different port numbers; that way we have execution of the main program while also being able to transmit any global variables being changed in the main program as a background process (hence why I have it as a thread in the client).
I am not having luck getting both to bind. Executing the processes as separate programs works, but when they are run together, only the main execution socket seems to bind and go through proper execution (while the background socket is waiting to bind).