I'm getting started with the Azure IoT SDK C-Library by using the IoT_Hub Device Method samples.
Does anybody know if the SDK provides a function to deserialize the JSON message payload? There are some good examples for payload serialization to JSON, but I wasn't able to find the counterpart.
I'm quite sure the SDK has some functionalities for JSON deserialization, e.g. something like:
BEGIN_NAMESPACE(WeatherStation);
DECLARE_MODEL(ContosoAnemometer,
WITH_DATA(ascii_char_ptr, DeviceId),
WITH_DATA(int, WindSpeed),
WITH_DATA(float, Temperature),
WITH_DATA(float, Humidity),
WITH_ACTION(TurnFanOn)
);
END_NAMESPACE(WeatherStation);
static int DeviceMethodCallback(const char* method_name, const unsigned char* payload, ...)
{
(void)userContextCallback;
ContosoAnemometer* myWeather = CREATE_MODEL_INSTANCE(WeatherStation, ContosoAnemometer);
DESERIALIZE(myWeather, payload)
printf("Device Id: %i\r\n", myWeather->DeviceId);
// etc. etc.
}
In the Azure IoT SDK for C,it uses serializer library to serialize messages to send, but there is no couterpart(DESERIALIZE) for receiving messages.Please see
more about serializer. In serializer component, you will find jsondecoder.c, it defines some method for decode json data.
And more, you will find the parson component. It can be used to deserialize the object from json string.You can refer to the following code.
jsonstr
{"desString":"P7svG%2BLoUZEbB8Le5jP1%2BpuX2OVWLE4xWMzFcYFCRvNvDlcFVm%2B8z2VFO%2F%2BaEB8UAMa%2FZ0GGhooGNMWFE98Zmw%3D%3D","caller":{"mobile":"13996130361"},"accountId":"b5091dc91d700c6bf714e5fc446797d3","tmpTime":1428545890,"otherParam":"{id:12}","participant":[{"mobile":"18623582801"}],"servletUrl":"http://192.168.1.1:8090/xdr"}
C Code
JSON_Value *root_value=NULL;
root_value = json_parse_string(jsonstr);
JSON_Object *root_object;
if(json_value_get_type(root_value) == JSONObject)
{
root_object = json_value_get_object(root_value);
const char *desString = json_object_get_string(root_object, "desString");
if(desString!=NULL)strncpy(pPost->desString,desString,LENGTH128-1);
const char *accountId = json_object_get_string(root_object, "accountId");
if(accountId!=NULL)strncpy(pPost->accountId,accountId,LENGTH32);
double tmpTime = json_object_get_number(root_object, "tmpTime");
const char *caller = json_object_dotget_string(root_object,"caller.mobile");
if(caller!=NULL)strncpy(pPost->caller,caller,LENGTH16-1);
const char *servletUrl = json_object_dotget_string(root_object,"servletUrl");
if(servletUrl!=NULL)strncpy(pPost->servletUrl,servletUrl,LENGTH128-1);
const char *otherParam = json_object_dotget_string(root_object,"otherParam");
if(otherParam!=NULL)strncpy(pPost->otherParam,otherParam,LENGTH128-1);
JSON_Array *array;
array = json_object_get_array(root_object, "participant");
int i =0;
for(i;i<json_array_get_count(array);i++)
{
JSON_Object *tmp = json_array_get_object(array,i);
if(tmp!=NULL)
{
const char *mobile = json_object_get_string(tmp,"mobile");
if(mobile!=NULL)strncpy(pPost->callee,mobile,LENGTH16-1);
}
}
}
if(root_value)json_value_free(root_value);
Related
I have a basic contract that looks like this:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
pragma abicoder v2;
contract testStruct {
struct Example {
uint256 number;
address user;
}
Example public example;
function set_struct(Example memory _example) public {
example = _example;
}
}
I have tried using this sdk like this.
//Create the transaction
const transaction = new ContractExecuteTransaction()
.setContractId(newContractId)
.setGas(100_000_000)
.setFunction("set_struct", new ContractFunctionParameters()
.addBytesArray(byte[][] structInBytes)
Some data type are not presented in the SDK. How can I call a smart contract and pass a complex type like a struct ?
If you are using structs as inputs/outputs to your contracts, or data types that aren't supported by the SDKs, you should check this example repo out which shows how to use commonly known libraries (web3.js, ethers.js, web3.j and abiDecode.js) to encode and decode contract function parameters and results https://github.com/hashgraph/hedera-smart-contracts-libs-lab
For example:
// get the constructor parameter
// .slice(2) to remove leading '0x'
const constructParameterAsHexString = abiInterface.encodeDeploy([constructMessage]).slice(2);
// convert to a Uint8Array
const constructorParametersAsUint8Array = Buffer.from(constructParameterAsHexString, 'hex');
I am trying to learn Kotlin/Native C interop
I exported some Kotlin classes as C dynamic Lib and succeeded in access methods with primitive return types
But When trying to access class members in a instance object which returned by a method, the object contains something named as pinned
Code sample:
#Serializable
data class Persons (
val results: Array<Result>,
val info: Info
)
class RandomUserApiJS {
fun getPersonsDirect() : Persons {
return runBlocking {
RandomUserApi().getPersons()
}
}
}
Now when using them in C codeblocks,
In this image, note that the persons obj only showing a field named pinned and no other member functions found.
Since I don't know that much in C/C++ and can't investigate further.
Please help me to understand to access instance members of Kotlin Class in exported C lib?
Header file for ref:
https://gist.github.com/RageshAntony/a0b9007376084fa8b213b022b58f9886
for your gist
https://gist.github.com/RageshAntony/a0b9007376084fa8b213b022b58f9886
I modified the following:
// I comment this annotation
// #Serializable
data class Persons(
val results: List<Result>,
val info: Info,
/**
* the Result's properties too many
* I will use a simple data class for this example
* how to get c array from Persons (also suitable any iterable)
*/
val testList: List<Simple>,
) {
public fun toJson() = Json.encodeToString(this)
companion object {
public fun fromJson(json: String) = Json.decodeFromString<Persons>(json)
}
val arena = Arena()
fun getTestListForC(size: CPointer<IntVar>): CPointer<COpaquePointerVar> {
size.pointed.value = testList.size
return arena.allocArray<COpaquePointerVar>(testList.size) {
this.value = StableRef.create(testList[it]).asCPointer()
}
}
fun free() {
arena.clear()
}
}
/**
* kotlin <-> c bridge is primitive type
* like int <-> Int
* like char* <-> String
* so the Simple class has two primitive properties
*/
data class Simple(
val name: String,
val age: Int,
)
#include <stdio.h>
#include "libnative_api.h"
int main(int argc, char **argv) {
libnative_ExportedSymbols* lib = libnative_symbols();
libnative_kref_MathNative mn = lib->kotlin.root.MathNative.MathNative();
const char *a = lib->kotlin.root.MathNative.mul(mn,5,6); // working
printf ("Math Resullt %s\n",a);
libnative_kref_RandomUserApiJS pr = lib->kotlin.root.RandomUserApiJS.RandomUserApiJS();
libnative_kref_Persons persons = lib->kotlin.root.RandomUserApiJS.getPersonsDirect(pr);
// when accessing above persons obj, only a field 'pinned' availabe, nothing else
int size;
libnative_kref_Simple* list = (libnative_kref_Simple *)lib->kotlin.root.Persons.getTestListForC(persons, &size);
printf("size = %d\n", size);
for (int i = 0; i < size; ++i) {
const char *name = lib->kotlin.root.Simple.get_name(list[i]);
int age = lib->kotlin.root.Simple.get_age(list[i]);
printf("%s\t%d\n", name, age);
}
lib->kotlin.root.Persons.free(persons);
return 0;
}
// for output
Math Resullt The answer is 30
size = 3
name1 1
name2 2
name3 3
But I don't think calling kotlin lib through C is a good behavior, because kotlin native is not focused on improving performance for now, in my opinion, all functions that can be implemented with kotlin native can find solutions implemented in pure c, So I'm more focused on how to access the c lib from kotlin. Of course, it's a good solution if you absolutely need to access klib from c, but I'm still not very satisfied with it, then I may create a github template to better solve kotlin-interop from c.But that's not the point of this answer.
I'm using the parson library to decode a json message body sent from a backend (AzureIoTHub direct method call). My string is always decoded as type JSONString instead of JSONObject so I cannot extract and keys and values. I think something is wrong with my string in the payload buffer but I'm stuck on what it is. ANy help is appreciated.
Here are two examples of different json strings stored in payload_buffer variable and neither work.
"{'device': '65'}"
JSON Type: 2
or
"{"device": "3445667"}"
JSON Type: 2
uint8_t payload_buffer[448];
JSON_Value *root_value = NULL;
JSON_Object *root_object = NULL;
JSON_Value *device_name = NULL;
const char* device;
printf("%.*s \r\n", (INT)insert_index, (CHAR *)&payload_buffer );
root_value = json_parse_string((const char *)&payload_buffer[0]);
if (root_value != NULL)
{
if (json_value_get_type(root_value) == JSONObject)
{
root_object=json_value_get_object(root_value);
device_name = json_object_dotget_value (root_object, "device");
device = json_value_get_string(device_name);
if (device != NULL)
{
printf("device: %s", device );
}
}
else
{
printf("JSON Type: %u \r\n", json_value_get_type(root_value));
}
}
For parson library to interpret a buffer as a JSONObject and not a JSONString you cannot have the buffer start and end with " character. Once I edited my buffer to this
{"device": "3445667"}
my code was able to parse the JSON object correctly.
I am attempting to use the cJSON library, written by Dave Gamble, to read in the following JSON request:
{"id":"8358441244995838759","jsonrpc":"2.0","method":"addext",
"params":["<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>
<trunks id=\"0\"><end_ch>3</end_ch>
<gateway>172.20.222.52</gateway>
<interface_type>E231</interface_type>
<name>Mumbai_Avaya</name>
<start_ch>12</start_ch>
<sub_type>E1PRI</sub_type></trunks>"]}
I am able to retrieve the "id" and "method" by using below code, but not able to retrieve or print the values inside "params" which is an XML string.
I want to print whatever inside the "params".
cJSON *cjson, *method_obj;
char *methodname;
char *params;
cjson = cJSON_Parse(buf);
method_obj = cJSON_GetObjectItem(cjson, "method");
methodname = method_obj->valuestring;
printf("method name %s\n", methodname);
method_obj = cJSON_GetObjectItem(cjson, "id");
id = method_obj->valueint;
char *str = method_obj->valuestring;
printf("id %s\n", str);
method_obj = cJSON_GetObjectItem(cjson, "params");
params=method_obj->valuestring;
printf("Params [ ] %s\n", params);
Please provide any suggestion.
Thanks in Advance.
Either change method_obj->valuestring to method_obj->child->valuestring (after checking that child != NULL), or have the service, that generates the JSON request, not use an array if none is needed.
params of field type is JSON Array.
use cJSON_GetArrayItem (and cJSON_GetArraySize) API like this:
method_obj = cJSON_GetObjectItem(cjson, "params");
int size = cJSON_GetArraySize(method_obj);
for(int i = 0; i < size; ++i){
params = cJSON_GetArrayItem(method_obj, i)->valuestring;
printf("Params [ ] %s\n", params);
}
I am trying to use ap_parse_form_data to parse a POST request:
request_rec* R = ...;
apr_array_header_t* H;
ap_parse_form_data(R, NULL, &H, -1, 1 << 20);
I would like to have two operations on H:
Get an entry by the key of "foo":
const char* val = ap_get_header(H, "foo");
And walking all key/values:
while (ap_has_more_headers(H))
{
const char* key = ap_get_next_header_key(H);
const char* value = ap_get_next_header_value(H);
...
}
Does anyone know how to do this or where it is documented? (ap_get_header, ap_has_more_headers, ap_get_next_header_key and ap_get_next_header_value are imaginary API calls to show what I want to do.)
Also do I need to release H somehow?
A working example of using ap_parse_form_data in these two use cases would be great.