ESP-IDF NimBLE Control the Relay and send the relay status to Client - bluetooth-lowenergy

I am so new in BLE and I found a code from github for send and receive ble data.
My question how can I convert the printf("Data from the client: %.*s\n", ctxt->om->om_len, ctxt->om->om_data);receive BLE data.
Its mean ı want to create a pointer for stored this value. Its need to be int or a thing of the hex value.
Thank you for your help.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include <stdio.h>
#include "esp_log.h"
#include "esp_nimble_hci.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "sdkconfig.h"
#include "string.h"
char *TAG = "BLE-Server";
uint8_t ble_addr_type;
void ble_app_advertise(void);
// Write data to ESP32 defined as server
static int device_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
{
printf("Data from the client: %.*s\n", ctxt->om->om_len, ctxt->om->om_data);
return 0;
}
// Read data from ESP32 defined as server
static int device_read(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
{
os_mbuf_append(ctxt->om, "Data from the server", strlen("Data from the server"));
return 0;
}
// Array of pointers to other service definitions
// UUID - Universal Unique Identifier
static const struct ble_gatt_svc_def gatt_svcs[] = {
{.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(0x180), // Define UUID for device type
.characteristics = (struct ble_gatt_chr_def[]){
{.uuid = BLE_UUID16_DECLARE(0xFEF4), // Define UUID for reading
.flags = BLE_GATT_CHR_F_READ,
.access_cb = device_read},
{.uuid = BLE_UUID16_DECLARE(0xDEAD), // Define UUID for writing
.flags = BLE_GATT_CHR_F_WRITE,
.access_cb = device_write},
{0}}},
{0}};
// BLE event handling
static int ble_gap_event(struct ble_gap_event *event, void *arg)
{
switch (event->type)
{
// Advertise if connected
case BLE_GAP_EVENT_CONNECT:
ESP_LOGI("GAP", "BLE GAP EVENT CONNECT %s", event->connect.status == 0 ? "OK!" : "FAILED!");
if (event->connect.status != 0)
{
ble_app_advertise();
}
break;
// Advertise again after completion of the event
case BLE_GAP_EVENT_ADV_COMPLETE:
ESP_LOGI("GAP", "BLE GAP EVENT");
ble_app_advertise();
break;
default:
break;
}
return 0;
}
// Define the BLE connection
void ble_app_advertise(void)
{
// GAP - device name definition
struct ble_hs_adv_fields fields;
const char *device_name;
memset(&fields, 0, sizeof(fields));
device_name = ble_svc_gap_device_name(); // Read the BLE device name
fields.name = (uint8_t *)device_name;
fields.name_len = strlen(device_name);
fields.name_is_complete = 1;
ble_gap_adv_set_fields(&fields);
// GAP - device connectivity definition
struct ble_gap_adv_params adv_params;
memset(&adv_params, 0, sizeof(adv_params));
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; // connectable or non-connectable
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; // discoverable or non-discoverable
ble_gap_adv_start(ble_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL);
}
// The application
void ble_app_on_sync(void)
{
ble_hs_id_infer_auto(0, &ble_addr_type); // Determines the best address type automatically
ble_app_advertise(); // Define the BLE connection
}
// The infinite task
void host_task(void *param)
{
nimble_port_run(); // This function will return only when nimble_port_stop() is executed
}
void app_main(void)
{
nvs_flash_init(); // 1 - Initialize NVS flash using
esp_nimble_hci_and_controller_init(); // 2 - Initialize ESP controller
nimble_port_init(); // 3 - Initialize the host stack
ble_svc_gap_device_name_set("BLE-Server"); // 4 - Initialize NimBLE configuration - server name
ble_svc_gap_init(); // 4 - Initialize NimBLE configuration - gap service
ble_svc_gatt_init(); // 4 - Initialize NimBLE configuration - gatt service
ble_gatts_count_cfg(gatt_svcs); // 4 - Initialize NimBLE configuration - config gatt services
ble_gatts_add_svcs(gatt_svcs); // 4 - Initialize NimBLE configuration - queues gatt services.
ble_hs_cfg.sync_cb = ble_app_on_sync; // 5 - Initialize application
nimble_port_freertos_init(host_task); // 6 - Run the thread
gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
int level = 0;
while (true) {
gpio_set_level(GPIO_NUM_4, level);
level = !level;
vTaskDelay(300 / portTICK_PERIOD_MS);
}
}

You can just copy the data to an array of bytes/uint8_t and use it.
I think it’s not wise to use a pointer to this data, because it’s not static.
For example:
uint8_t incoming[36];
memcpy(incoming,ctxt->om->om_data,ctxt->om->om_len);

The Results
1st=50 2nd=51 3rd=52 4nd=0
Receive Data = 1234
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include <stdio.h>
#include "esp_log.h"
#include "esp_nimble_hci.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "sdkconfig.h"
#include "string.h"
char *TAG = "BLE-Server";
uint8_t ble_addr_type;
uint8_t rx_data[4];
void ble_app_advertise(void);
// Write data to ESP32 defined as server
static int device_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
{
printf("Data from the client: %.*s\n", ctxt->om->om_len, ctxt->om->om_data);
memcpy(rx_data,ctxt->om->om_data,ctxt->om->om_len);
return 0;
}
// Read data from ESP32 defined as server
static int device_read(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
{
os_mbuf_append(ctxt->om, "Data from the server", strlen("Data from the server"));
return 0;
}
// Array of pointers to other service definitions
// UUID - Universal Unique Identifier
static const struct ble_gatt_svc_def gatt_svcs[] = {
{.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(0x180), // Define UUID for device type
.characteristics = (struct ble_gatt_chr_def[]){
{.uuid = BLE_UUID16_DECLARE(0xFEF4), // Define UUID for reading
.flags = BLE_GATT_CHR_F_READ,
.access_cb = device_read},
{.uuid = BLE_UUID16_DECLARE(0xDEAD), // Define UUID for writing
.flags = BLE_GATT_CHR_F_WRITE,
.access_cb = device_write},
{0}}},
{0}};
// BLE event handling
static int ble_gap_event(struct ble_gap_event *event, void *arg)
{
switch (event->type)
{
// Advertise if connected
case BLE_GAP_EVENT_CONNECT:
ESP_LOGI("GAP", "BLE GAP EVENT CONNECT %s", event->connect.status == 0 ? "OK!" : "FAILED!");
if (event->connect.status != 0)
{
ble_app_advertise();
}
break;
// Advertise again after completion of the event
case BLE_GAP_EVENT_ADV_COMPLETE:
ESP_LOGI("GAP", "BLE GAP EVENT");
ble_app_advertise();
break;
default:
break;
}
return 0;
}
// Define the BLE connection
void ble_app_advertise(void)
{
// GAP - device name definition
struct ble_hs_adv_fields fields;
const char *device_name;
memset(&fields, 0, sizeof(fields));
device_name = ble_svc_gap_device_name(); // Read the BLE device name
fields.name = (uint8_t *)device_name;
fields.name_len = strlen(device_name);
fields.name_is_complete = 1;
ble_gap_adv_set_fields(&fields);
// GAP - device connectivity definition
struct ble_gap_adv_params adv_params;
memset(&adv_params, 0, sizeof(adv_params));
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; // connectable or non-connectable
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; // discoverable or non-discoverable
ble_gap_adv_start(ble_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL);
}
// The application
void ble_app_on_sync(void)
{
ble_hs_id_infer_auto(0, &ble_addr_type); // Determines the best address type automatically
ble_app_advertise(); // Define the BLE connection
}
// The infinite task
void host_task(void *param)
{
nimble_port_run(); // This function will return only when nimble_port_stop() is executed
}
void app_main(void)
{
nvs_flash_init(); // 1 - Initialize NVS flash using
esp_nimble_hci_and_controller_init(); // 2 - Initialize ESP controller
nimble_port_init(); // 3 - Initialize the host stack
ble_svc_gap_device_name_set("BLE-Server"); // 4 - Initialize NimBLE configuration - server name
ble_svc_gap_init(); // 4 - Initialize NimBLE configuration - gap service
ble_svc_gatt_init(); // 4 - Initialize NimBLE configuration - gatt service
ble_gatts_count_cfg(gatt_svcs); // 4 - Initialize NimBLE configuration - config gatt services
ble_gatts_add_svcs(gatt_svcs); // 4 - Initialize NimBLE configuration - queues gatt services.
ble_hs_cfg.sync_cb = ble_app_on_sync; // 5 - Initialize application
nimble_port_freertos_init(host_task); // 6 - Run the thread
gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
int level = 0;
while (true) {
uint8_t ctc_data;
ctc_data=rx_data[2];
gpio_set_level(GPIO_NUM_4, level);
level = !level;
printf("1st=%u 2nd=%u 3rd=%u 4nd=%u\n",rx_data[1],ctc_data,rx_data[3],rx_data[4]);
printf("Receive Data = %.*s\n", 4, rx_data);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}

Related

ESP32 FreeRTOS pin interrupt ISR handler core 0 panic (C++)

Currently I am trying to attach a pin interrupt whose ISR is to call xTaskResumeFromISR or xQueueSendFromISR. The ISR gets called correctly, but the code to execute results in a core 0 panic.
Here are the implementation details.
PlatformIO: platform = espressif32 # 6.0.1, framework = arduino, board = esp32dev
Header file (Worker.h)
#pragma once
#include <Arduino.h>
class Worker {
public:
Worker(uint8_t pinExtInterrupt);
bool startTask(void);
protected:
// static wrapper for task creation
static void staticRun(void *arg) {
reinterpret_cast<Worker *>(arg)->run();
}
// actual task's logic
void run(void);
// static interrupt handler
static void staticIsrHandler(void* arg);
// actual interrupt handler
void isrHandler();
TaskHandle_t _taskHandle = nullptr;
uint8_t _pinExtInterrupt;
};
Source file (Worker.cpp)
#include "Worker.h"
Worker::Worker(uint8_t pinExtInterrupt) {
_pinExtInterrupt = pinExtInterrupt;
pinMode(pinExtInterrupt, INPUT);
}
bool Worker::startTask(void) {
BaseType_t xReturned = xTaskCreate(staticRun, "Worker", 2048, this, 5, &_taskHandle);
gpio_set_intr_type(static_cast<gpio_num_t>(_pinExtInterrupt), GPIO_INTR_NEGEDGE);
gpio_install_isr_service(0);
gpio_isr_handler_add(static_cast<gpio_num_t>(_pinExtInterrupt), staticIsrHandler, NULL);
return true;
}
void Worker::run(void) {
for (;;) {
vTaskSuspend(NULL);
// LOGIC
}
}
void IRAM_ATTR Worker::staticIsrHandler(void* arg) {
reinterpret_cast<Worker*>(arg)->isrHandler();
}
void IRAM_ATTR Worker::isrHandler() {
xTaskResumeFromISR(_taskHandle); // ###### THIS LINE THROWS THE EXCEPTION ######
}
Error
Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
0x400d1d00:0x3ffbeaac in Worker::isrHandler() at ...
But what works is if you replace xTaskResumeFromISR e.g. with digitalWrite(..).
Need to fix the problem above.
Your call here:
gpio_isr_handler_add(static_cast<gpio_num_t>(_pinExtInterrupt), staticIsrHandler, NULL);
assigns a null pointer for the ISR handler's context data. As a result, when your static ISR is called:
void IRAM_ATTR Worker::staticIsrHandler(void* arg) {
reinterpret_cast<Worker*>(arg)->isrHandler();
}
arg is a null pointer, causing the access to _taskHandle to fail here:
void IRAM_ATTR Worker::isrHandler() {
xTaskResumeFromISR(_taskHandle);
}
If you replace your gpio_isr_handler_add call with the following:
gpio_isr_handler_add(static_cast<gpio_num_t>(_pinExtInterrupt), staticIsrHandler, this);
everything should work.

What is rosidl_runtime_c__double__Sequence type?

I'm trying to use a teensy 4.1 as an interface between an encoder and ROS thanks to micro-ros (arduino version).
I would like to publish position of a wheel to the /jointState topic with the teensy but there is no example on the micro-ros arduino Github repo.
I've tried to inspect the sensormsgs/msg/jointState message struct but everything is a bit fuzzy and I don't understand how to make it works. I can't understand what is rosidl_runtime_c__double__Sequence type.
I've tried several things but I always get an error about operand types
no match for 'operator=' (operand types are 'rosidl_runtime_c__String' and 'const char [18]')
msg.name.data[0] = "drivewhl_1g_joint";
Here is my arduino code
#include <micro_ros_arduino.h>
#include <stdio.h>
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <sensor_msgs/msg/joint_state.h>
rcl_publisher_t publisher;
sensor_msgs__msg__JointState msg;
rclc_executor_t executor;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;
rcl_timer_t timer;
#define LED_PIN 13
#define RCCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){error_loop();}}
#define RCSOFTCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){}}
void error_loop(){
while(1){
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
delay(100);
}
}
void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
RCLC_UNUSED(last_call_time);
if (timer != NULL) {
RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
//
//Do not work
//msg.name=["drivewhl_1g_joint","drivewhl_1d_joint","drivewhl_2g_joint","drivewhl_2d_joint"];
//msg.position=["1.3","0.2", "0","0"];
msg.name.size = 1;
msg.name.data[0] = "drivewhl_1g_joint";
msg.position.size = 1;
msg.position.data[0] = 1.85;
}
}
void setup() {
set_microros_transports();
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
delay(2000);
allocator = rcl_get_default_allocator();
//create init_options
RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));
// create node
RCCHECK(rclc_node_init_default(&node, "micro_ros_arduino_node", "", &support));
// create publisher
RCCHECK(rclc_publisher_init_default(
&publisher,
&node,
ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, JointState),
"JointState"));
// create timer,
const unsigned int timer_timeout = 1000;
RCCHECK(rclc_timer_init_default(
&timer,
&support,
RCL_MS_TO_NS(timer_timeout),
timer_callback));
// create executor
RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));
RCCHECK(rclc_executor_add_timer(&executor, &timer));
}
void loop() {
delay(100);
RCSOFTCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));
}
I'm a beginner with Ros and C, it may be a very dumb question but I don't know how to solve it. Thanks for your help !
rosidl_runtime_c__String__Sequence is a structure used to old string data that is to be transmitted. Specifically it is a sequence of rosidl_runtime_c__String data. You're running into an error because rosidl_runtime_c__String is also a struct itself with no custom operators defined. Thus, your assignment fails since the types are not directly convertible. What you need to do instead is use the rosidl_runtime_c__String.data field. You can see slightly more info here
void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
RCLC_UNUSED(last_call_time);
if (timer != NULL) {
//msg.name=["drivewhl_1g_joint","drivewhl_1d_joint","drivewhl_2g_joint","drivewhl_2d_joint"];
//msg.position=["1.3","0.2", "0","0"];
msg.name.size = 1;
msg.name.data[0].data = "drivewhl_1g_joint";
msg.name.data[0].size = 17; //Size in bytes excluding null terminator
msg.position.size = 1;
msg.position.data[0] = 1.85;
RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
}
}
I also spent quite some time trying to get publishing JointState message from my esp32 running microros, and also couldn't find working example. Finally, i was successful, maybe it will help someone.
In simple words:
.capacity contains max number of elements
.size contains actual number of elements (strlen in case of string)
.data should be allocated as using malloc as .capacity * sizeof()
each string within sequence should be allocated separately
This is my code that allocates memory for 12 joints, named j0-j11. Good luck!
...
// Declarations
rcl_publisher_t pub_joint;
sensor_msgs__msg__JointState joint_state_msg;
...
// Create publisher
RCCHECK(rclc_publisher_init_default(&pub_joint, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, JointState),
"/hexapod/joint_state"));
//Allocate memory
joint_state_msg.name.capacity = 12;
joint_state_msg.name.size = 12;
joint_state_msg.name.data = (std_msgs__msg__String*) malloc(joint_state_msg.name.capacity*sizeof(std_msgs__msg__String));
for(int i=0;i<12;i++) {
joint_state_msg.name.data[i].data = malloc(5);
joint_state_msg.name.data[i].capacity = 5;
sprintf(joint_state_msg.name.data[i].data,"j%d",i);
joint_state_msg.name.data[i].size = strlen(joint_state_msg.name.data[i].data);
}
joint_state_msg.position.size=12;
joint_state_msg.position.capacity=12;
joint_state_msg.position.data = malloc(joint_state_msg.position.capacity*sizeof(double));
joint_state_msg.velocity.size=12;
joint_state_msg.velocity.capacity=12;
joint_state_msg.velocity.data = malloc(joint_state_msg.velocity.capacity*sizeof(double));
joint_state_msg.effort.size=12;
joint_state_msg.effort.capacity=12;
joint_state_msg.effort.data = malloc(joint_state_msg.effort.capacity*sizeof(double));
for(int i=0;i<12;i++) {
joint_state_msg.position.data[i]=0.0;
joint_state_msg.velocity.data[i]=0.0;
joint_state_msg.effort.data[i]=0.0;
}
....
//Publish
RCSOFTCHECK(rcl_publish(&pub_joint, &joint_state_msg, NULL));

CAN bus port access via socket; non-blocking solution needed

I've got an application where I will be using a standalone C programming to read a CAN bus port with a socket. The user interface on this is Qt/QML code. I would like to use a non-blocking approach to call the bin program and either return nothing or return a string of the CAN packet.
The application will be low speed (just monitoring key presses, etc) so speed is not an issue. The current approach involves writing data from the socket program to a file, then having ANOTHER C program take the file and echo the string back to QML. UGH! Seems very messy. A simple Go/NoGo call would be easier. Here's the code I've got so far.
Thanks for any comments.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/can.h>
#include <linux/can/raw.h>
// Returns 0 if no errors, > 0 if errors found
int main(void) {
struct ifreq ifr;
struct can_frame frame;
struct sockaddr_can addr;
int s; // CAN socket descriptor
int nbytes; // Number of bytes read from CAN socket
char run_daemon = 0; // Set to 1 to run as a daemon process
char show_errors = 0; // Set to 1 to print errors
char *ifname = "can0"; // Define the CAN driver for use
if (run_daemon) // Skip the daemon call if not enabled
daemon(1,1);
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
if (show_errors)
perror("Error while opening RAW socket");
return 1;
}
strcpy (ifr.ifr_name, ifname);
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
if (show_errors)
perror("Error in socket bind");
return 2;
}
// Loop here for daemon process
while (1) {
// Read CAN frame data
nbytes = read(s, &frame, sizeof(struct can_frame));
// If data is ready, process it
if (nbytes > 0) {
// Print all relevent frame data to QML
printf("%d ",frame.can_id);
printf("%d ",frame.can_dlc);
if(frame.can_dlc>0) printf("%d ",frame.data[0]);
if(frame.can_dlc>1) printf("%d ",frame.data[1]);
if(frame.can_dlc>2) printf("%d ",frame.data[2]);
if(frame.can_dlc>3) printf("%d ",frame.data[3]);
if(frame.can_dlc>4) printf("%d ",frame.data[4]);
if(frame.can_dlc>5) printf("%d ",frame.data[5]);
if(frame.can_dlc>6) printf("%d ",frame.data[6]);
if(frame.can_dlc>7) printf("%d ",frame.data[7]);
printf("\n");
}
if (!run_daemon) { // Exit if daemon is not running
close(s); // Close the CAN socket
return 0;
}
}
return 0; // Should never get here !!!
}

Updating ac value for Qtimer

I am using qt tool for mini2440.
I make a gui for i2c adc having starti2c and stopi2c.
All things are working well: it reads value of signal when starti2c button press, but I want this value to be updated. I know that Qtimer can be used, but how can I do it?
Here is the code:
# include <termio.h>
# include <time.h>
# include <string.h>
# include <sys/time.h>
HelloForm::HelloForm(QWidget* parent, const char* name, WFlags fl):
HelloBaseForm(parent, name, fl)
{
connect(PushButton1,SIGNAL(clicked()),this,SLOT(starti2c()));
connect(PushButton2,SIGNAL(clicked()),this,SLOT(stopi2c()));
}
HelloForm::~HelloForm()
{
}
//*********************Code for getting i2c**************************//
char HelloForm::geti2c()
{
char buf[100];
char buff[100];
char valuee;
int m1;
char con_buff[10];
int fd=open("/dev/i2c/0",O_RDWR);
if (fd<0)
{
Message->setText(" NOT ABLE TO OPEN THE DRIVER ");
}
else
{
Message->setText(" I2C IS WORKING ");
}
int io,wbyte,rbyte,i;
//********i2cdetect and read************
buf[0]=0x48;
buf[1]=0x00;
buf[2]=0x91;
io=ioctl(fd,I2C_SLAVE,0x48);
if(io<0)
{
Message->setText(" ");
Message->setText("error ioctl");
}
else
{
wbyte=write(fd,buf,3);
// write all three control word to arm
usleep(1*1000);
}
if(wbyte!=3)
{
Message->setText("error write");
Message->setText(QString::number(wbyte));
rbyte=read(fd,buff,10);
//ADC->setText(buff);
sscanf(buff,"%c",&valuee);
m1=int(valuee);
return(m1);
}
void HelloForm::starti2c()
{
while(1)
{
float adc_val=0;
adc_val=geti2c();
adc_val=(adc_val*5)/255.00;
usleep(1*1000);
ADC->setText(QString::number(adc_val));
}
}
//***********stop********//
void HelloForm::stopi2c()
{
ADC->setText(" ");
Message->setText("Stopped");
}
Hopefully this will get you started - it creates a timer which times out every 1000 milli seconds. The timer's timeout signal is connected to the same slot that your PushButton1 is connected to - starti2c.
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(starti2c()));
timer->start(1000);
That code should be placed below where you have your 2 connection statements.

connecting a signal of widget in a plasmoid

I am new to Qt and am trying to connect the cilicked signal o a push button with a function hile writing a plasmoid. I am trying to use an external function as a public with Plasma::PushButton type object so that I can use it to connect it with the clicked signal? With gtk it was as simple as on_...._clicked do this but isnt there a simple way in qt, where we can do away with the need to use slots?
#include "plasma-tutorial1.h"
#include<string.h>
#include <stdlib.h>
#include <QGraphicsLinearLayout>
#include <QPainter>
#include <QFontMetrics>
#include <QSizeF>
#include <QTextEdit>
#include <plasma/svg.h>
#include <plasma/theme.h>
#include <plasma/widgets/lineedit.h>
#include <plasma/widgets/pushbutton.h>
#include <plasma/widgets/textedit.h>
//PlasmaTutorial1 mainf;
themainfunction(int choice,Plasma::LineEdit *m_lineEdit,
Plasma::TextEdit *m_displaytext)
{
char buffer[100];
const char *inp=(const char *)malloc(sizeof(char)*100);
QString input;
input=m_lineEdit->text();
QByteArray byteArray = input.toUtf8();
inp = byteArray.constData();
char *expression;
expression=(char *)malloc(sizeof(char)*100);
strcpy(expression,"sudo apt-");
switch(choice)
{
case 1:{
strcat(expression,"get install ");
strcat(expression,inp);
break;
};
case 2:{
strcat(expression,"get remove ");
strcat(expression,inp);
break;
};
case 3:{
strcat(expression,"cache search ");
strcat(expression,inp);
break;
};
};
/*
FILE* in;
FILE* ptr=fopen("new.txt","w");
FILE *popen();
if(!(in = popen("cal","r")))
{return;}
while(fgets(buffer, 100, in) != NULL) {
*/
m_displaytext->append("yeah!");
// fprintf(ptr,"%s",buffer);
//}
//pclose(in);
//fclose(ptr);
}
PlasmaTutorial1::PlasmaTutorial1(QObject *parent, const QVariantList &args)
: Plasma::Applet(parent, args),
m_svg(this),
m_icon("document")
{
m_svg.setImagePath("widgets/background");
// this will get us the standard applet background, for free!
setBackgroundHints(DefaultBackground);
resize(200, 200);
}
PlasmaTutorial1::~PlasmaTutorial1()
{
if (hasFailedToLaunch()) {
// Do some cleanup here
} else {
// Save settings
}
}
void PlasmaTutorial1::init()
{
/* // A small demonstration of the setFailedToLaunch function
if (m_icon.isNull()) {
setFailedToLaunch(true, "No world to say hello");
}*/
Counter rt;
QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
layout->setOrientation(Qt::Vertical); //so widgets will be stacked up/down
m_lineEdit = new Plasma::LineEdit(this);
m_lineEdit->setText("Enter the package name here");
m_displaytext = new Plasma::TextEdit(this);
m_displaytext->setText("Terminal");
m_installButton = new Plasma::PushButton(this);
m_installButton->setText("Install");
connect(m_installButton, SIGNAL(clicked()),&rt,SLOT(themainfunction(1,m_lineEdit,m_displaytext)));
m_removeButton = new Plasma::PushButton(this);
m_removeButton->setText("Remove");
// m_removeButton->clicked()
connect(m_removeButton, SIGNAL(clicked()),&rt,SLOT(themainfunction(2,m_lineEdit,m_displaytext)));
m_searchButton = new Plasma::PushButton(this);
m_searchButton->setText("Search");
connect(m_searchButton, SIGNAL(clicked()),&rt,SLOT(themainfunction(3,m_lineEdit,m_displaytext)));
layout->addItem(m_lineEdit);
layout->addItem(m_installButton);
layout->addItem(m_removeButton);
layout->addItem(m_searchButton);
layout->addItem(m_displaytext);
m_displaytext->append("yo baby!");
}
/*
void PlasmaTutorial1::paintInterface(QPainter *p,
const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
{
p->setRenderHint(QPainter::SmoothPixmapTransform);
p->setRenderHint(QPainter::Antialiasing);
// Now we draw the applet, starting with our svg
m_svg.resize((int)contentsRect.width(), (int)contentsRect.height());
m_svg.paint(p, (int)contentsRect.left(), (int)contentsRect.top());
// We place the icon and text
p->drawPixmap(7, 0, m_icon.pixmap((int)contentsRect.width(),(int)contentsRect.width()-14));
p->save();
p->setPen(Qt::white);
p->drawText(contentsRect,
Qt::AlignBottom | Qt::AlignHCenter,
"Hello Plasmoid!");
p->restore();
}
*/
// This is the command that links your applet to the .desktop file
K_EXPORT_PLASMA_APPLET(tutorial1, PlasmaTutorial1)
#include "plasma-tutorial1.moc"
say i want to connect themainfunction() upon clicked signal of install button . how do i do it? how can I derive a class in plasma?
i got where was i missing out. We cannot pass objects as arguments in slot functions. Now it is running smooth. thanx for all your replies.

Resources