ESP32 (ESP-IDF) "driver/twai.h" CAN Data Transmission is working but Receive function is not working using CAN/TWAI - esp32

I saw a YouTube video with someone who used a similar code, and it was working perfectly for him (YouTube Video: link: https://youtu.be/bxzWuIqfn9Y). He used "driver/can.h" which has been removed from v5.0 of ESP-IDF because CAN and TWAI are the same.
More details:
Issue raised on GitHub: https://github.com/espressif/esp-idf/issues/10757#issue-1582253298
IDF version used: v5.0 and v4.4.4
Operating System used: Windows
IDE used to program and flash code: VS Code IDE
This is my code:
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "stdio.h"
#include "stdlib.h"
#include "driver/twai.h"
void twai_setup_and_install(){
//Initialize configuration structures using macro initializers
twai_general_config_t g_config = {
.mode = TWAI_MODE_NORMAL,
.tx_io = GPIO_NUM_5,
.rx_io = GPIO_NUM_4,
.clkout_io = TWAI_IO_UNUSED,
.bus_off_io = TWAI_IO_UNUSED,
.tx_queue_len = 5,
.rx_queue_len = 5,
.alerts_enabled = TWAI_ALERT_NONE,
.clkout_divider = 0
};
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
// Install TWAI driver
if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
printf("Driver installed\n");
} else {
printf("Failed to install driver\n");
return;
}
// Start TWAI driver
if (twai_start() == ESP_OK) {
printf("Driver started\n");
} else {
printf("Failed to start driver\n");
return;
}
}
void new_message(twai_message_t *message, uint32_t id, uint8_t dlc, uint8_t *data)
{
message->flags = TWAI_MSG_FLAG_NONE;
message->identifier = id;
message->data_length_code = dlc;
for (int i = 0; i < dlc; i++) {
message->data[i] = data[i];
}
printf("Message created\nID: %ld DLC: %d Data:\t", message->identifier, message->data_length_code);
for (int i = 0; i < message->data_length_code; i++) {
printf("%d\t", message->data[i]);
}
printf("\n");
}
void transmit_message(twai_message_t *message)
{
if (twai_transmit(message, pdMS_TO_TICKS(1000)) == ESP_OK) {
printf("Message queued for transmission\n");
} else {
printf("Failed to send message\n");
}
}
void receive_message(twai_message_t *message)
{
if (twai_receive(message, pdMS_TO_TICKS(1000)) == ESP_OK) {
printf("Message received:\n");
printf("ID: %ld DLC: %d Data:\t", message->identifier, message->data_length_code);
for (int i = 0; i < message->data_length_code; i++) {
(message->extd)?printf("Extended ID"):printf("Standard ID");
printf("%d\t", message->data[i]);
}
} else {
printf("Failed to receive message\n");
}
}
void app_main()
{
twai_setup_and_install();
twai_message_t message;
twai_message_t message1;
// Set the data to send
uint8_t data[8] = {rand() % 255, rand() % 255, rand() % 255,
rand() % 255, rand() % 255, rand() % 255, rand() % 255, rand() % 255};
while(true){
// Create a new message
new_message(&message, 0x123, 8, data);
// Transmit the message to a queue
transmit_message(&message);
// Receive the message from the queue
receive_message(&message1);
// Wait for 1 second
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
If anyone can help me as soon as possible, it would be really appreciated.
Sincere Regards.
Steps followed:
I used ESP-IDF v5.0 with VS Code.
I used the documentation to obtain the code for sender and receiver.
I used a tested and functional MCP2515 module as my transceiver for the same.
The Tx is broadcasting perfectly, but the Rx is not working for the above code.
Expected Output:
Message received:
ID: 0x123 DLC: 8 Data: 1 2 3 4 5 6 7 8
In my source code, I have implemented random data bits, so data may vary
Actual Output:
Failed to receive message

Related

Electric UI example ESP32 websockets example code issue

This is the example code given for Electric UI's ESP32 websockets intergration.
// This example was written with the ESP8266 and ESP32 as the target hardware.
// Connects to a wifi access point and runs a websockets server as a transport for eUI.
// The ws path is hinted to the UI over the serial connection which ruggedises connection discovery.
// Base wifi libraries from the ESP library pack
#include "WiFi.h"
#include "WiFiMulti.h"
#include "WiFiClientSecure.h"
// Websockets library https://github.com/Links2004/arduinoWebSockets
#include "WebSocketsServer.h"
#include "electricui.h"
#define LED_PIN LED_BUILTIN
// Define default network credentials
char * wifi_ssid = "ssid";
char * wifi_pass = "password";
uint8_t ws_connected = 0; //state indication
uint8_t ws_port = 80;
char ws_path[] = "ws(s)://255.255.255.255:81";
// Simple variables to modify the LED behaviour
uint8_t blink_enable = 1; //if the blinker should be running
uint8_t led_state = 0; //track if the LED is illuminated
uint16_t glow_time = 200; //in milliseconds
// Keep track of when the light turns on or off
uint32_t led_timer = 0;
//example variables
uint8_t example_uint8 = 21;
uint16_t example_uint16 = 321;
uint32_t example_uint32 = 654321;
float example_float = 3.141592;
char demo_string[] = "ESP32 Test Board";
eui_message_t dev_msg_store[] = {
EUI_UINT8( "wsc", ws_connected),
EUI_CHAR_ARRAY( "ws", ws_path ),
EUI_UINT8( "led_blink", blink_enable ),
EUI_UINT8( "led_state", led_state ),
EUI_UINT16( "lit_time", glow_time ),
EUI_UINT8( "ui8", example_uint8 ),
EUI_UINT16( "i16", example_uint16 ),
EUI_UINT32( "i32", example_uint32 ),
EUI_FLOAT( "fPI", example_float ),
EUI_CHAR_ARRAY_RO( "name", demo_string ),
};
WiFiMulti WiFiMulti;
WebSocketsServer webSocket = WebSocketsServer(ws_port);
void tx_putc(uint8_t *data, uint16_t len);
void ws_tx_putc(uint8_t *data, uint16_t len);
eui_interface_t comm_links[] = {
EUI_INTERFACE(&tx_putc),
EUI_INTERFACE(&ws_tx_putc),
};
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
uint8_t * iter = payload;
uint8_t * end = payload + length;
switch(type)
{
case WStype_DISCONNECTED:
ws_connected = 2;
break;
case WStype_CONNECTED:
ws_connected = 3;
break;
case WStype_TEXT:
// send data to all connected clients
// webSocket.broadcastTXT("message here");
break;
case WStype_BIN:
while( iter < end )
{
eui_parse(*iter++, &comm_links[1]);
}
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
ws_connected = 4;
break;
}
}
void wifi_handle()
{
if( WiFiMulti.run() == WL_CONNECTED )
{
//we have a wifi connection
if(!ws_connected)
{
webSocket.begin();
webSocket.onEvent(webSocketEvent);
ws_connected = 1;
// The hint is formatted like ws://255.255.255.255:81
memset( ws_path, 0, sizeof(ws_path) ); //clear the string first
snprintf(ws_path, sizeof(ws_path), "ws://%s:%d", WiFi.localIP().toString().c_str(), ws_port);
glow_time = 200;
// Using Arduino Strings
// String ws_path_string = "ws://" + WiFi.localIP().toString().c_str() + ":" + String(ws_port);
// ws_path_string.toCharArray(ws_path, sizeof(ws_path));
}
else
{
webSocket.loop();
}
}
else
{
//no connection, try again later
ws_connected = 0;
}
}
void eui_callback( uint8_t message )
{
switch(message)
{
case EUI_CB_TRACKED:
// UI recieved a tracked message ID and has completed processing
break;
case EUI_CB_UNTRACKED:
{
// UI passed in an untracked message ID
// Grab parts of the inbound packet which are are useful
eui_header_t header = comm_links[0].packet.header;
uint8_t *name_rx = comm_links[0].packet.id_in;
void *payload = comm_links[0].packet.data_in;
// See if the inbound packet name matches our intended variable
if( strcmp( (char *)name_rx, "talk" ) == 0 )
{
webSocket.broadcastTXT("hello over websockets");
glow_time = 50;
}
}
break;
case EUI_CB_PARSE_FAIL:
break;
}
}
void setup()
{
Serial.begin(115200);
pinMode( LED_BUILTIN, OUTPUT );
//eUI setup
comm_links[0].interface_cb = &eui_callback;
eui_setup_interfaces(comm_links, 2);
EUI_TRACK(dev_msg_store);
eui_setup_identifier("esp32", 5);
WiFiMulti.addAP(wifi_ssid, wifi_pass);
led_timer = millis();
}
void loop()
{
wifi_handle();
while(Serial.available() > 0)
{
eui_parse(Serial.read(), &comm_links[0]);
}
if( blink_enable )
{
// Check if the LED has been on for the configured duration
if( millis() - led_timer >= glow_time )
{
led_state = !led_state; //invert led state
led_timer = millis();
}
}
digitalWrite( LED_PIN, led_state ); //update the LED to match the intended state
}
void tx_putc( uint8_t *data, uint16_t len )
{
Serial.write( data, len );
}
void ws_tx_putc( uint8_t *data, uint16_t len )
{
webSocket.broadcastBIN( data, len);
}
When I enter my SSID and Password the serial monitor just displays:
E (2462) wifi:Association refused temporarily, comeback time 200 mSec
However the LED is blinking as it should.... The Electric UI shows no devices found....

How to recieve a Direct Method on the ESP32 with azure-sdk-for-c-arduino

For a school project I am using IoT Hub to connect between different devices (ESP32), The intention is to use a web application to retrieve data from a device. I want to do this by using a Direct Method.
Now I have seen in the past some direct methods using python and how I can use this in Azure Functions but not yet on an ESP32. By the way, I am programming in C on the ESP32.
Does anyone have an example code for this? I am not finding really much info about direct methods in C with the library "azure-sdk-for-c-arduino".
Thanks in advance
My code at the moment (This is test code):
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/*
This is an Arduino-based Azure IoT Hub sample for ESPRESSIF ESP32 boards.
It uses our Azure Embedded SDK for C to help interact with Azure IoT.
For reference, please visit https://github.com/azure/azure-sdk-for-c.
To connect and work with Azure IoT Hub you need an MQTT client, connecting, subscribing
and publishing to specific topics to use the messaging features of the hub.
Our azure-sdk-for-c is an MQTT client support library, helping composing and parsing the
MQTT topic names and messages exchanged with the Azure IoT Hub.
This sample performs the following tasks:
- Synchronize the device clock with a NTP server;
- Initialize our "az_iot_hub_client" (struct for data, part of our azure-sdk-for-c);
- Initialize the MQTT client (here we use ESPRESSIF's esp_mqtt_client, which also handle the tcp connection and TLS);
- Connect the MQTT client (using server-certificate validation, SAS-tokens for client authentication);
- Periodically send telemetry data to the Azure IoT Hub.
To properly connect to your Azure IoT Hub, please fill the information in the `iot_configs.h` file.
*/
//Variabeles for drukknop
const int PushButton = 35;
//Variables for weight sensor;
double weight = 5.0;
// C99 libraries
#include <cstdlib>
#include <string.h>
#include <time.h>
// Libraries for MQTT client and WiFi connection
#include <WiFi.h>
#include <mqtt_client.h>
// Azure IoT SDK for C includes
#include <az_core.h>
#include <az_iot.h>
#include <azure_ca.h>
// Libraries for SendingJson
#include <ArduinoJson.h>
// Additional sample headers
#include "AzIoTSasToken.h"
#include "SerialLogger.h"
#include "iot_configs.h"
// When developing for your own Arduino-based platform,
// please follow the format '(ard;<platform>)'.
#define AZURE_SDK_CLIENT_USER_AGENT "c/" AZ_SDK_VERSION_STRING "(ard;esp32)"
// Utility macros and defines
#define sizeofarray(a) (sizeof(a) / sizeof(a[0]))
#define NTP_SERVERS "pool.ntp.org", "time.nist.gov"
#define MQTT_QOS1 1
#define DO_NOT_RETAIN_MSG 0
#define SAS_TOKEN_DURATION_IN_MINUTES 60
#define UNIX_TIME_NOV_13_2017 1510592825
#define PST_TIME_ZONE -8
#define PST_TIME_ZONE_DAYLIGHT_SAVINGS_DIFF 1
#define GMT_OFFSET_SECS (PST_TIME_ZONE * 3600)
#define GMT_OFFSET_SECS_DST ((PST_TIME_ZONE + PST_TIME_ZONE_DAYLIGHT_SAVINGS_DIFF) * 3600)
// Translate iot_configs.h defines into variables used by the sample
static const char* ssid = IOT_CONFIG_WIFI_SSID;
static const char* password = IOT_CONFIG_WIFI_PASSWORD;
static const char* host = IOT_CONFIG_IOTHUB_FQDN;
static const char* mqtt_broker_uri = "mqtts://" IOT_CONFIG_IOTHUB_FQDN;
static const char* device_id = IOT_CONFIG_DEVICE_ID;
static const int mqtt_port = AZ_IOT_DEFAULT_MQTT_CONNECT_PORT;
// Memory allocated for the sample's variables and structures.
static esp_mqtt_client_handle_t mqtt_client;
static az_iot_hub_client client;
static char mqtt_client_id[128];
static char mqtt_username[128];
static char mqtt_password[200];
static uint8_t sas_signature_buffer[256];
static unsigned long next_telemetry_send_time_ms = 0;
static char telemetry_topic[128];
static uint8_t telemetry_payload[100];
static uint32_t telemetry_send_count = 0;
#define INCOMING_DATA_BUFFER_SIZE 128
static char incoming_data[INCOMING_DATA_BUFFER_SIZE];
// Auxiliary functions
#ifndef IOT_CONFIG_USE_X509_CERT
static AzIoTSasToken sasToken(
&client,
AZ_SPAN_FROM_STR(IOT_CONFIG_DEVICE_KEY),
AZ_SPAN_FROM_BUFFER(sas_signature_buffer),
AZ_SPAN_FROM_BUFFER(mqtt_password));
#endif // IOT_CONFIG_USE_X509_CERT
static void connectToWiFi()
{
Logger.Info("Connecting to WIFI SSID " + String(ssid));
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Logger.Info("WiFi connected, IP address: " + WiFi.localIP().toString());
}
static void initializeTime()
{
Logger.Info("Setting time using SNTP");
configTime(GMT_OFFSET_SECS, GMT_OFFSET_SECS_DST, NTP_SERVERS);
time_t now = time(NULL);
while (now < UNIX_TIME_NOV_13_2017)
{
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
Logger.Info("Time initialized!");
}
void receivedCallback(char* topic, byte* payload, unsigned int length)
{
Logger.Info("Received [");
Logger.Info(topic);
Logger.Info("]: ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println("");
}
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
switch (event->event_id)
{
int i, r;
case MQTT_EVENT_ERROR:
Logger.Info("MQTT event MQTT_EVENT_ERROR");
break;
case MQTT_EVENT_CONNECTED:
Logger.Info("MQTT event MQTT_EVENT_CONNECTED");
r = esp_mqtt_client_subscribe(mqtt_client, AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, 1);
if (r == -1)
{
Logger.Error("Could not subscribe for cloud-to-device messages.");
}
else
{
Logger.Info("Subscribed for cloud-to-device messages; message id:" + String(r));
}
break;
case MQTT_EVENT_DISCONNECTED:
Logger.Info("MQTT event MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
Logger.Info("MQTT event MQTT_EVENT_SUBSCRIBED");
break;
case MQTT_EVENT_UNSUBSCRIBED:
Logger.Info("MQTT event MQTT_EVENT_UNSUBSCRIBED");
break;
case MQTT_EVENT_PUBLISHED:
Logger.Info("MQTT event MQTT_EVENT_PUBLISHED");
break;
case MQTT_EVENT_DATA:
Logger.Info("MQTT event MQTT_EVENT_DATA");
for (i = 0; i < (INCOMING_DATA_BUFFER_SIZE - 1) && i < event->topic_len; i++)
{
incoming_data[i] = event->topic[i];
}
incoming_data[i] = '\0';
Logger.Info("Topic: " + String(incoming_data));
for (i = 0; i < (INCOMING_DATA_BUFFER_SIZE - 1) && i < event->data_len; i++)
{
incoming_data[i] = event->data[i];
}
incoming_data[i] = '\0';
if (String(incoming_data) == "GETWEIGHT")
{
Logger.Info("Send Data To The Cloud ");
sendTelemetry();
}
else
{
Logger.Info("Data: " + String(incoming_data));
}
break;
case MQTT_EVENT_BEFORE_CONNECT:
Logger.Info("MQTT event MQTT_EVENT_BEFORE_CONNECT");
break;
default:
Logger.Error("MQTT event UNKNOWN");
break;
}
return ESP_OK;
}
static void initializeIoTHubClient()
{
az_iot_hub_client_options options = az_iot_hub_client_options_default();
options.user_agent = AZ_SPAN_FROM_STR(AZURE_SDK_CLIENT_USER_AGENT);
if (az_result_failed(az_iot_hub_client_init(
&client,
az_span_create((uint8_t*)host, strlen(host)),
az_span_create((uint8_t*)device_id, strlen(device_id)),
&options)))
{
Logger.Error("Failed initializing Azure IoT Hub client");
return;
}
size_t client_id_length;
if (az_result_failed(az_iot_hub_client_get_client_id(
&client, mqtt_client_id, sizeof(mqtt_client_id) - 1, &client_id_length)))
{
Logger.Error("Failed getting client id");
return;
}
if (az_result_failed(az_iot_hub_client_get_user_name(
&client, mqtt_username, sizeofarray(mqtt_username), NULL)))
{
Logger.Error("Failed to get MQTT clientId, return code");
return;
}
Logger.Info("Client ID: " + String(mqtt_client_id));
Logger.Info("Username: " + String(mqtt_username));
}
static int initializeMqttClient()
{
#ifndef IOT_CONFIG_USE_X509_CERT
if (sasToken.Generate(SAS_TOKEN_DURATION_IN_MINUTES) != 0)
{
Logger.Error("Failed generating SAS token");
return 1;
}
#endif
esp_mqtt_client_config_t mqtt_config;
memset(&mqtt_config, 0, sizeof(mqtt_config));
mqtt_config.uri = mqtt_broker_uri;
mqtt_config.port = mqtt_port;
mqtt_config.client_id = mqtt_client_id;
mqtt_config.username = mqtt_username;
#ifdef IOT_CONFIG_USE_X509_CERT
Logger.Info("MQTT client using X509 Certificate authentication");
mqtt_config.client_cert_pem = IOT_CONFIG_DEVICE_CERT;
mqtt_config.client_key_pem = IOT_CONFIG_DEVICE_CERT_PRIVATE_KEY;
#else // Using SAS key
mqtt_config.password = (const char*)az_span_ptr(sasToken.Get());
#endif
mqtt_config.keepalive = 30;
mqtt_config.disable_clean_session = 0;
mqtt_config.disable_auto_reconnect = false;
mqtt_config.event_handle = mqtt_event_handler;
mqtt_config.user_context = NULL;
mqtt_config.cert_pem = (const char*)ca_pem;
mqtt_client = esp_mqtt_client_init(&mqtt_config);
if (mqtt_client == NULL)
{
Logger.Error("Failed creating mqtt client");
return 1;
}
esp_err_t start_result = esp_mqtt_client_start(mqtt_client);
if (start_result != ESP_OK)
{
Logger.Error("Could not start mqtt client; error code:" + start_result);
return 1;
}
else
{
Logger.Info("MQTT client started");
return 0;
}
}
/*
#brief Gets the number of seconds since UNIX epoch until now.
#return uint32_t Number of seconds.
*/
static uint32_t getEpochTimeInSecs()
{
return (uint32_t)time(NULL);
}
static void establishConnection()
{
connectToWiFi();
initializeTime();
initializeIoTHubClient();
(void)initializeMqttClient();
}
static void getTelemetryPayload(az_span payload, az_span* out_payload)
{
az_span original_payload = payload;
payload = az_span_copy(
payload, AZ_SPAN_FROM_STR("{ \"deviceId\": "));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( IOT_CONFIG_DEVICE_ID ));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( "," ));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( "\" weight\": "));
(void)az_span_u32toa(payload, weight , &payload);
payload = az_span_copy(payload, AZ_SPAN_FROM_STR(" }"));
payload = az_span_copy_u8(payload, '\0');
*out_payload = az_span_slice(original_payload, 0, az_span_size(original_payload) - az_span_size(payload) - 1);
}
static void sendTelemetry()
{
az_span telemetry = AZ_SPAN_FROM_BUFFER(telemetry_payload);
Logger.Info("Sending telemetry ...");
// The topic could be obtained just once during setup,
// however if properties are used the topic need to be generated again to reflect the
// current values of the properties.
if (az_result_failed(az_iot_hub_client_telemetry_get_publish_topic(
&client, NULL, telemetry_topic, sizeof(telemetry_topic), NULL)))
{
Logger.Error("Failed az_iot_hub_client_telemetry_get_publish_topic");
return;
}
getTelemetryPayload(telemetry, &telemetry);
if (esp_mqtt_client_publish(
mqtt_client,
telemetry_topic,
(const char*)az_span_ptr(telemetry),
az_span_size(telemetry),
MQTT_QOS1,
DO_NOT_RETAIN_MSG)
== 0)
{
Logger.Error("Failed publishing");
}
else
{
Logger.Info("Message published successfully");
}
}
// Arduino setup and loop main functions.
void setup()
{
establishConnection();
pinMode(PushButton, INPUT);
}
void loop()
{
if (WiFi.status() != WL_CONNECTED)
{
connectToWiFi();
}
#ifndef IOT_CONFIG_USE_X509_CERT
else if (sasToken.IsExpired())
{
Logger.Info("SAS token expired; reconnecting with a new one.");
(void)esp_mqtt_client_destroy(mqtt_client);
initializeMqttClient();
}
#endif
int Push_button_state = digitalRead(PushButton);
// if condition checks if push button is pressed
if ( Push_button_state == HIGH )
{
Serial.println("De Button Is ingedrukt");
sendTelemetry();
delay(500);
}
}
The idea is that when I send a Direct Method "GETWEIGHT" I get a json value back.
In your initializeMqttClient method, you can add the following line.
mqtt_client.setCallback(receivedCallback);
Your receivedCallback method can have the following definition (code from a Microsoft sample)
void receivedCallback(char* topic, byte* payload, unsigned int length)
{
Logger.Info("Received [");
Logger.Info(topic);
Logger.Info("]: ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println("");
}
You mentioned you want to retrieve data from the device, so you probably want to respond to the message. This is done by sending a message on the right topic. You need to include the status (for instance a 200 indicating 'OK') and the ID of the direct method. This id is included when you receive the direct method. For instance, if you receive a direct method with ID 42, you can respond to it by publishing:
void RespondToDirectMethod()
{
mqtt_client.publish("$iothub/methods/res/200/?$rid=42", "", false);
}

Sending a string to UART gives garbage with printf

I'm trying to format data sent over a USB UART with printf and it's giving me garbage. I can send a simple string and that works but anything I try to format gives junk. Looking through the code I think it has to do with my string not being in program space but I'm not sure.
Here is my main:
void main(void) {
CPU_PRESCALE(CPU_16MHz);
init_uart();
int degree = 0;
char buffer[50];
while(1) {
degree = (degree + 1) % 360;
send_str(PSTR("\n\nHello!!!\n\n"));
memset(buffer, 0, 50);
sprintf_P(buffer, PSTR("%d degrees\n"), degree);
send_str(buffer);
_delay_ms(20);
}
}
The output looks like this:
Hello!!!
����/�������(/����#Q��������
Hello!!!
����/�������(/����#Q��������
The USB UART code I found in a tutorial. The relevant parts look like this:
void send_str(const char *s)
{
char c;
while (1) {
c = pgm_read_byte(s++);
if (!c) break;
usb_serial_putchar(c);
}
}
int8_t usb_serial_putchar(uint8_t c)
{
uint8_t timeout, intr_state;
// if we're not online (enumerated and configured), error
if (!usb_configuration) return -1;
// interrupts are disabled so these functions can be
// used from the main program or interrupt context,
// even both in the same program!
intr_state = SREG;
cli();
UENUM = CDC_TX_ENDPOINT;
// if we gave up due to timeout before, don't wait again
if (transmit_previous_timeout) {
if (!(UEINTX & (1<<RWAL))) {
SREG = intr_state;
return -1;
}
transmit_previous_timeout = 0;
}
// wait for the FIFO to be ready to accept data
timeout = UDFNUML + TRANSMIT_TIMEOUT;
while (1) {
// are we ready to transmit?
if (UEINTX & (1<<RWAL)) break;
SREG = intr_state;
// have we waited too long? This happens if the user
// is not running an application that is listening
if (UDFNUML == timeout) {
transmit_previous_timeout = 1;
return -1;
}
// has the USB gone offline?
if (!usb_configuration) return -1;
// get ready to try checking again
intr_state = SREG;
cli();
UENUM = CDC_TX_ENDPOINT;
}
// actually write the byte into the FIFO
UEDATX = c;
// if this completed a packet, transmit it now!
if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
SREG = intr_state;
return 0;
}

Unable to communicate between libwebsocket as client and socket.io as server

This is client code by using libwebsocket version 1.5
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <syslog.h>
#include <sys/time.h>
#include <unistd.h>
#include <libwebsockets.h>
static volatile int force_exit = 0;
static int state, command_received = 0, forked = 0;
#define MAX_ECHO_PAYLOAD 1400
#define LOCAL_RESOURCE_PATH "./"
struct per_session_data {
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_ECHO_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
unsigned int len;
};
//for temporary storing data from tcpdump
struct per_session_data data1;
static int callback_echo(struct libwebsocket_context *context, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len)
{
struct per_session_data *pss = (struct per_session_data *)user;
int n;
switch (reason) {
/* when the callback is used for client operations --> */
case LWS_CALLBACK_CLOSED:
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf("Closed\n");
state = 0;
break;
case LWS_CALLBACK_ESTABLISHED:
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf("Client connected\n");
state = 2;
break;
/* we will receive our packet here*/
case LWS_CALLBACK_RECEIVE:
case LWS_CALLBACK_CLIENT_RECEIVE:
printf("Rx from server: %s\n", (char *)in);
if (!strcmp((char *)in, "tcpdump"))
{
command_received = 1;
}
break;
/* we will send our packet here */
case LWS_CALLBACK_CLIENT_WRITEABLE:
printf("client writing to server\n");
pss->len = sprintf((char *)&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
printf("Data: %s\n\n\n\n\n\n\n", &pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);
//error handling for write fail and partial writes
if (n < 0) {
printf("ERROR %d writing to socket, hanging up\n", n);
return -1;
}
if (n < (int)pss->len) {
printf("Partial write\n");
return -1;
}
break;
default:
printf("default...\n");
break;
}
return 0;
}
/* List of available protocols */
static struct libwebsocket_protocols protocols[] = {
{
"default", /* name */
callback_echo, /* callback */
sizeof(struct per_session_data) /* per_session_data_size */
},
{
NULL, NULL, 0 /* End of list */
}
};
void sighandler(int sig)
{
force_exit = 1;
}
int main(int argc, char **argv)
{
//pipe stuff
int pipe_fd[2];
if (pipe(pipe_fd) < 0)
{
perror("PIPE:");
exit(-1);
}
//for libwebsocket_service
int n = 0;
//test port can be overidden
int port = 9000;
struct libwebsocket_context *context;
int opts = 0;
char interface_name[128] = "";
const char *interface = NULL;
int use_ssl = 0;
char ssl_cert[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
char ssl_key[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
int listen_port = 80;
struct lws_context_creation_info info;
char passphrase[256];
char uri[256] = "/";
char address[256], ads_port[256 + 30];
//lws servicing time intervals
int rate_us = 250000;
unsigned int oldus = 0;
struct libwebsocket *wsi;
//should check this
int debug_level = 2;
memset(&info, 0, sizeof info);
lwsl_notice("Built to support client operations\n");
//re-configuring server ip and port here
if (argc == 3)
{
strncpy(address, argv[1], sizeof(address) - 1);
address[sizeof(address) - 1] = '\0';
port = atoi(argv[2]);
}
else if (argc == 1)
{
strncpy(address, "localhost", sizeof(address) - 1);
address[sizeof(address) - 1] = '\0';
port = 9000;
}
else
{
printf("Try: ./client.exec <ip> <port>\n");
exit(-1);
}
/* we will only try to log things according to our debug_level */
setlogmask(LOG_UPTO (LOG_DEBUG));
openlog("lwsts", 0, LOG_DAEMON);
/* tell the library what debug level to emit and to send it to syslog */
lws_set_log_level(debug_level, lwsl_emit_syslog);
lwsl_notice("libwebsockets echo test - "
"(C) Copyright 2010-2015 Andy Green <andy#warmcat.com> - "
"licensed under LGPL2.1\n");
lwsl_notice("Running in client mode\n");
listen_port = CONTEXT_PORT_NO_LISTEN;
lwsl_info("requiring server cert validation againts %s\n", ssl_cert);
info.ssl_ca_filepath = ssl_cert;
info.port = listen_port;
info.iface = interface;
info.protocols = protocols;
#ifndef LWS_NO_EXTENSIONS
info.extensions = libwebsocket_get_internal_extensions();
#endif
info.gid = -1;
info.uid = -1;
info.options = opts;
context = libwebsocket_create_context(&info);
if (context == NULL) {
lwsl_err("libwebsocket init failed\n");
return -1;
}
signal(SIGINT, sighandler);
n = 0;
while (n >= 0 && !force_exit)
{
//do connect only once
if (!state) {
state = 1;
printf("Client connecting to %s:%u....\n", address, port);
address[sizeof(address) - 1] = '\0';
sprintf(ads_port, "%s:%u", address, port & 65535);
wsi = libwebsocket_client_connect(context, address, port, use_ssl, uri, ads_port, ads_port, NULL, -1);
if (!wsi) {
printf("Client failed to connect to %s:%u\n", address, port);
goto bail;
}
}
if (command_received == 1 && !forked)
{
printf("Going to fork\n");
forked = 1;
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("FORK:");
exit(-1);
}
else if (child_pid == 0)
{
close(pipe_fd[0]);
printf("Starting tcpdump\n");
if (dup2(pipe_fd[1], 1) < 0)
{
perror("DUP2:");
exit(-1);
}
//closing the connection to server for child
libwebsocket_context_destroy(context);
closelog();
char *cmd[] = {"tcpdump", "-i", "any", NULL};
if (execv("/usr/sbin/tcpdump", cmd) < 0)
{
perror("EXECV:");
exit(-1);
}
}
}
/* if (forked == 1)
{
close(pipe_fd[1]);
}
*/
if (command_received == 1)
{
//stay here if the pipe is empty else try to read max 1400 bytes of data
while ((data1.len = read(pipe_fd[0], data1.buf + LWS_SEND_BUFFER_PRE_PADDING, 1400)) <= 0);
//check if server wants any service
//printf("%s\n\n\n\n\n\n\n", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
libwebsocket_callback_on_writable(context, wsi);
}
//This fn times out every 10usec
n = libwebsocket_service(context, 10);
}
//bail: jump from while loop also if connect fails
bail:
libwebsocket_context_destroy(context);
printf("libwebsockets-test-echo exited cleanly\n");
closelog();
return 0;
}
This is my server code by using socket.io
var io = require('socket.io')();
var middleware = require('socketio-wildcard')();
io.use(middleware);
io.on('connection', function(socket) {
console.log('On socket connection')
socket.on('*', function(event, data){
console.log("---- Event ----- : " + JSON.stringify(event));
console.log("---- Data ----- : " + JSON.stringify(data))
});
});
io.listen(9000, 'localhost');
The client is unable to connect with server. when i tested client with strace it infinitely does receive as below
recv(8, "", 1, 0) = 0
recv(8, "", 1, 0) = 0
recv(8, "", 1, 0) = 0
.
.
.
.
Please point out my mistake. Any help is appreciated.
Thanks

Why i am not able to read multiple strings in the server file?

While working in client-server programming, I have passed 3 strings in client, which will be received by server and it should be printed in there 3 times. (i.e I have used a 'for' loop which will do the read & write operations in client & server side respectively.), but in server only the 1st string is getting printed.
Please explain,
Here is my code
server.c
#include "head.h"
void readstr(int connfd ,char [][20]);
//void writestr(char * ,int);
int main(int c ,char *v[])
{
// socket declarations,etc
sd =socket( AF_INET ,SOCK_STREAM ,0);
// Binding socket
retbind =bind(sd ,(struct sockaddr*)&serveraddress ,sizeof(serveraddress
));
listen(sd ,4);
for(;;)
{
printf("i am waiting for client\n");
len =sizeof(cliaddr);
connfd = accept(sd ,(struct sockaddr*)&cliaddr ,&len);
readstr(connfd ,databuf);
close(connfd);
}
return 0;
}
void readstr(int connfd ,char str[3] [20])
{
int pointer=0 ,i=0, n,pos=0;
memset(str ,'\0',sizeof(str));
for(i=0;i<3;i++)
{
while((n=read(connfd ,str[i] ,20)) >>0)
{
printf("Looping while\n");
pos =pos +n;
}
str[i][pos] ='\0';
}
for(i=0;i<3;i++)
{
printf("\n%s",str[i]);
}
}
client.c
#include "head.h"
void send1(int ,char*);
int main(int c,char*v[])
{
//Socket declarations, etc..
sd = socket(AF_INET ,SOCK_STREAM ,0);
//Connect
if(connect(sd,(struct sockaddr*)&serveraddress ,sizeof(serveraddress)) <
0)
{
printf("cannot connect to server");
exit(1);
}
for(i=0;i<3;i++)
{
memset(buf ,'\0',sizeof(buf));
printf("\n Enter the string : ");
fgets(buf[i],20,stdin);
len =strlen(buf[i]);
if(buf[i][len] =='\n')
buf[i][len]='\0';
send1(sd ,(char *)buf);
}
shutdown(sd ,SHUT_WR);
}
void send1(int sd ,char *str)
{
int n ,byteswritten =0, wr;
char buf[1024];
strcpy(buf ,str);
n =strlen(buf);
while(byteswritten < n)
{
printf("\nStarting to write in client side\n");
wr = write(sd , buf+byteswritten ,(n-byteswritten));
byteswritten+=wr;
}
printf("\n string sent %s" ,buf);
}
In server.c in readstr() you are not setting pos to zero before the next for iteration.
Also, there is strange line:
while((n=read(connfd ,str[i] ,20)) >>0)
Note ">>".

Resources