i'm trying to develop an application (written in ANSI C) for an OpenWrt router using libuci.
I've read this useful post: How to find out if the eth0 mode is static or dhcp?
and i've develop a piece of my application that is able to read network data (in this case i read if ppp is enabled) using uci library.
char path[]="network.ppp.enabled";
struct uci_ptr ptr;
struct uci_context *c = uci_alloc_context();
if(!c) return;
if (strcmp(typeCmd, "GET") == 0){
if ((uci_lookup_ptr(c, &ptr, path, true) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
if(ptr.flags & UCI_LOOKUP_COMPLETE)
strcpy(buffer, ptr.o->v.string);
uci_free_context(c);
printf("\n\nUCI result data: %s\n\n", buffer);
}
now i want try to SET new network data (so i want enable ppp -> set ppp to 1)
I've write:
}else if (strcmp(typeCmd, "SET") == 0){
if ((uci_lookup_ptr(c, &ptr, path, true) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
ptr.o->v.string = "1";
if ((uci_set(c, &ptr) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
if (uci_commit(c, struct uci_package **p, true) != UCI_OK){
uci_free_context(c);
return;
}
}
LibUci documentation is non-existent, there is just some info in the file uci.h, i don't know how fill uci_ptr struct, so i've retrieve it from uci_lookup_ptr , i've change ptr.o->v.string and launch uci_set with new params, but about uci_commit i don't know about struct uci_package **p.
Someone call share with me a bit of documentation or show me some examples?
Thanks a lot
The documentation is very thin on UCI. The way I figured it out is by using the uci_ptr's .value property from the uci structure.
Fromt that, I change the line:
ptr.o->v.string = "1";
to:
ptr.value = "1";
I also changed your commit line as follows:
uci_commit(ctx, &ptr.p, false);
That worked for me.
Related
I'm writing an auto display turn-off function with ESP32 on Arduino framework with PIO.
I have a Screen class for handling all of the screen functions.
void Screen::turn_off_screen(){
digitalWrite(SCREEN_ENABLE, LOW);
}
void turn_off_screen_wrapper()
{
Serial.println("turn_off_screen_wrapper called");
if (c_screen_Instance != nullptr)
{
c_screen_Instance->turn_off_screen();
}
}
void Screen::auto_display_power_off(int timeout){
Serial.println("auto_display_power_off called");
c_screen_Instance = this;
auto_off_timer = timerBegin(0, 80, true);
Serial.println("auto_off_timer ran");
timerAttachInterrupt(auto_off_timer, &turn_off_screen_wrapper, true);
Serial.println("timerAttachInterrupt ran");
//Converts given seconds from us to seconds
timerAlarmWrite(auto_off_timer,timeout*1000000,false);
timerAlarmEnable(auto_off_timer);
}
The code compiles however I get this when I run it on the board.
auto_display_power_off called
[E][esp32-hal-cpu.c:93] addApbChangeCallback(): duplicate func=400811F8 arg=3FFBDC54
auto_off_timer ran
The screen never gets turned off of course since the callback never runs. Any ideas why this is happening?
is c_screen_Instance global?
is auto_off_timer global?
Consider providing a bit more of your code.
But anyway.
bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
initApbChangeCallback();
apb_change_t * c = (apb_change_t*)malloc(sizeof(apb_change_t));
if(!c){
log_e("Callback Object Malloc Failed");
return false;
}
c->next = NULL;
c->prev = NULL;
c->arg = arg;
c->cb = cb;
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
if(apb_change_callbacks == NULL){
apb_change_callbacks = c;
} else {
apb_change_t * r = apb_change_callbacks;
// look for duplicate callbacks
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
if (r) {
log_e("duplicate func=%8p arg=%8p",c->cb,c->arg);
free(c);
xSemaphoreGive(apb_change_lock);
return false;
}
else {
c->next = apb_change_callbacks;
apb_change_callbacks-> prev = c;
apb_change_callbacks = c;
}
}
xSemaphoreGive(apb_change_lock);
return true;
}
This is addApbChangeCallback's declaration.
Your error comes from this line :
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
Where r it's a struct to hold all the callbacks.
This error indeed indicates this callback function was already assigned somewhere in your code. r is global, so your code is re-assigning the same callback twice.
Try to either only assign it once, or to unassign the function before assigning it again with removeApbChangeCallback(void * arg, apb_change_cb_t cb) or timerDetachInterrupt
I've also found a reported issue related to timerAttach on the current version here: https://github.com/espressif/arduino-esp32/issues/6730
Try to roll back the Platform PIO's version to a more stable one:
# instead of espressif32
platform = https://github.com/platformio/platform-espressif32.git#<tag-version>
Check on the git link for the available tags you can use.
Problem was that I was attaching the interrupt in the void loop(). Which would run way faster than the actual timer. After moving it to setup (Setup being a placeholder) I plan on having it on a Hardware interrupt it worked as expected.
I need to know at which offset into an xml string a specific arbitrary node somewhere in dom can be found after xmlReadMemory was used to get dom. The problem is I can't figure out where to get the xmlParserCtxtPtr from to pass as first argument to xmlParserFindNodeInfo because my entire process of parsing yields no such context; only a xmlDoc.
The following code worked for me (libxml2 documentation leaves little to desire, had to download source code and dig in the lib until I understood enough to hack this together). The key is:
xmlSetFeature(ctxt, "gather line info", (void *)&v);
Here is some code to illustrate:
const char *xml = ...
xmlParserCtxt *ctxt = NULL;
xmlDoc *doc = NULL;
if (!(ctxt = xmlCreateDocParserCtxt((const unsigned char *)xml)))
return -1;
int v = 1;
xmlSetFeature(ctxt, "gather line info", (void *)&v);
if (xmlParseDocument(ctxt) == -1)
{
xmlFreeParserCtxt(ctxt);
return -1;
}
else
{
if ((ctxt->wellFormed) || ctxt->recovery)
doc = ctxt->myDoc;
else
{
xmlFreeParserCtxt(ctxt);
return -1;
}
}
// use doc to get a node and then xmlParserFindNodeInfo(ctxt, node)
…
xmlFreeParserCtxt(ctxt);
so i am using jansson library and i want to set a value:
json_object_set_new(event, "error_code", json_integer(response->error_code));
The problem is that, i need to free response struct, but still use the value i have set in json_object_set_new.
Should i copy the value from response->error_code and how can i do that?
Some context:
plugin_response: {
if(!response->message && response->error_code == 0) {
response->error_code = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
if(response->error_cause == NULL) {
response->error_cause = g_strdup_printf("%s", "Invalid response");
}
}
json_t *event = json_object();
if(!response->message && response->error_code != 0) {
/* Prepare JSON error event */
json_object_set_new(event, "audiobridge", json_string("event"));
json_object_set_new(event, "error_code", json_integer(response->error_code));
json_object_set_new(event, "error", json_string(response->error_cause));
} else {
event = json_deep_copy(response->message);
}
if(root != NULL)
json_decref(root);
if(jsep != NULL)
json_decref(jsep);
g_free(transaction);
g_free(response);
return janus_plugin_result_new(JANUS_PLUGIN_OK, NULL, event);
}
EDIT: I am also using GLib, so if there is a nifty method for this, i am all ears.
Okey, i read this This article and i understood. I don't need to copy integer i am passing to json_integer(), because it's is not a pointer and is completely isolated from the structs integer.
i have a pointer problem:
SearchResults* pointy;
pointy = returnResults();
if(pointy != NULL && pointy->results[0] != NULL)
{
HandleResponse();
printf("sharp");
}else{
//do other things
}
if(pointy == NULL){
printf("blunt");
}
if(pointy->results[0] == NULL){
printf("wah!!!");
}
in the debugger the code correctly works and i get "sharp" but under the same conditions in the bash terminal i get "wah!!!"
typedef struct SearchResults
{
TreeNode* results[40];
int searchIndex;
} SearchResults;
SearchResults* lostAndFound;
SearchResults* returnResults()
{
return lostAndFound;
}
Found a Problem in both the debug and release variations there is a .csv file.. the debug reads and writes to it perfectly fine whereas the release seems to steamroll it into nothigness.
I want to load mono assemblies from memory. So instead of using the usual mono_domain_assembly_open I use mono_image_open_from_data. The returned image and assembly are OK and the status is MONO_IMAGE_OK.
m_valid = true;
mono_set_dirs(assembliesDir.c_str(), configDir.c_str());
MonoImageOpenStatus status = MONO_IMAGE_ERROR_ERRNO;
m_image = mono_image_open_from_data(data, size, 1, &status);
if(status != MONO_IMAGE_OK || m_image == NULL) {
m_valid = false;
return;
}
m_assembly = mono_assembly_load_from( m_image, assembliesName.c_str(), &status);
if(status != MONO_IMAGE_OK || m_assembly == NULL) {
m_valid = false;
return;
}
However when I try to get a class from the assembly using :
MonoClass *my_class = mono_class_from_name (m_image, name_space.c_str(), name.c_str());
I get my_class == NULL. When I use the usual mono_image_open_from_data Mono returns a valid class instance.
I suspect that the method doesn't load correctly all the references. Do you have any suggestions or workarounds ?