How to read json file from ESP8266's SPIFFS with ArduinoJSON 6? - esp8266

I am currently working on a project with ESP8266 (ESP-12E) and I need to store information in a json file (more convenient to access via the web interface and easier to manage than EEPROM for me).
My problem is the following: I'm using the latest version of ArduinoJSON (6), but I haven't seen many examples except on their site, and this code doesn't work for me :
void DeleteCycle(size_t idtodelete) {
File schedules = SPIFFS.open("/schedules.json", "r");
if(schedules && schedules.size()) {
DynamicJsonDocument schedulesjson(1300);
DeserializationError err = deserializeJson(schedulesjson, schedules);
Serial.println(err.c_str());
if (err) {
Serial.print(F("deserializeJson() failed with code "));
Serial.println(err.c_str());
}
else {
JsonArray array = schedulesjson.to<JsonArray>();
// array.remove(0);
serializeJson(array, Serial);
}
schedules.close();
}
else {
Serial.println("Failed to read file.");
}
}
I guess the problem is the JsonArray, it's empty !
But my JsonDocument is not, because if I do
JsonObject obj = schedulesjson[0];
String test = obj["name"];
Serial.println("Test : " + test);
I get the first key value (name) of my array at index 0
This is my first post on StackOverflow, I hope I did it right, thanks in advance for your help!

I answer myself because I found the solution to my problem: writing
schedulesjson.to<JsonArray>();
empties the json document, so you have to put it before
DeserializationError err = deserializeJson(schedulesjson, schedules);

Related

stub.GetHistoryKeys() reporting GetHistoryKeys() function undefined. when tried go build on my Chaincode

I am new to Hyperledger .I am using docker to run Hyperledger. Pulled hyperledger/fabric-peer:latest from Docker hub and
able to run stub.CreateTable() ,stub.GetRows() , stub.InsertRows() and some other functions in my Chaincode. But when i tried to run
stub.GetHistoryKeys() or stub.GetCompositeKeys() ...etc in my chaincode
It's reporting an error
stub.GetHistoryForKey undefined (type shim.ChaincodeStubInterface has no field
or method GetHistoryForKey)
I found that in my interface.go file there are no such functions . Googled a lot but found nothing .Can anyone tell the correct hyperledger/fabric-peer image to pull so that the above functions can run in Chaincode.
Please download latest version of fabric image, (
hyperledger/fabric-peer x86_64-1.1.0 ). It can be downloaded from script mentioned on hyperledger official website (Install binary)=> (https://hyperledger-fabric.readthedocs.io/en/latest/install.html. Can't paste url due to stackover flow policy issue). Once you have it. Create a go code. Simply add one json record on one key add then try to add some change some field of json and again add to same key. Once you have done that, fire the below code for gethistory:=>
func (s *SmartContract) getAllTransactionForid(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
fmt.Println("getAllTransactionForNumber called")
id:= args[0]
resultsIterator, err := APIstub.GetHistoryForKey(id)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()
// buffer is a JSON array containing historic values for the number
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
response, err := resultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{\"TxId\":")
buffer.WriteString("\"")
buffer.WriteString(response.TxId)
buffer.WriteString("\"")
buffer.WriteString(", \"Value\":")
// if it was a delete operation on given key, then we need to set the
//corresponding value null. Else, we will write the response.Value
//as-is (as the Value itself a JSON marble)
if response.IsDelete {
buffer.WriteString("null")
} else {
buffer.WriteString(string(response.Value))
}
buffer.WriteString(", \"Timestamp\":")
buffer.WriteString("\"")
buffer.WriteString(time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)).String())
buffer.WriteString("\"")
buffer.WriteString(", \"IsDelete\":")
buffer.WriteString("\"")
buffer.WriteString(strconv.FormatBool(response.IsDelete))
buffer.WriteString("\"")
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
if !bArrayMemberAlreadyWritten {
buffer.WriteString("No record found")
}
buffer.WriteString("]")
fmt.Printf("- getAllTransactionForNumber returning:\n%s\n", buffer.String())
return shim.Success(buffer.Bytes())
}
If still in doubt, please revert. I will give you my whole source code to make it work. But I hope this will make your problem go away :-)
At last I am able to figure it out to get the hyperledger images to support my chaincode.

Hashset handling to avoid stuck in loop during iteration

I'm working on image mining project, and I used Hashset instead of array to avoid adding duplicate urls while gathering urls, I reached to the point of code to iterate the Hashset that contains the main urls and within the iteration I go and download the the page of the main URL and add them to the Hashet, and go on , and during iteration I should exclude every scanned url, and also exclude ( remove ) every url that end with jpg, this until the Hashet of url count reaches 0, the question is that I faced endless looping in this iteration , where I may get url ( lets call it X )
1- I scan the page of url X
2- get all urls of page X ( by applying filters )
3- Add urls to the Hashset using unioinwith
4- remove the scanned url X
the problem comes here when one of the URLs Y, when scanned bring X again
shall I use Dictionary and the key as "scanned" ?? I will try and post the result here, sorry it comes to my mind after I posted the question...
I managed to solve it for one url, but it seems it happens with other urls to generate loop, so how to handle the Hashset to avoid duplicate even after removing the links,,, I hope that my point is clear.
while (URL_Can.Count != 0)
{
tempURL = URL_Can.First();
if (tempURL.EndsWith("jpg"))
{
URL_CanToSave.Add(tempURL);
URL_Can.Remove(tempURL);
}
else
{
if (ExtractUrlsfromLink(client, tempURL, filterlink1).Contains(toAvoidLoopinLinks))
{
URL_Can.Remove(tempURL);
URL_Can.Remove(toAvoidLoopinLinks);
}
else
{
URL_Can.UnionWith(ExtractUrlsfromLink(client, tempURL, filterlink1));
URL_Can.UnionWith(ExtractUrlsfromLink(client, tempURL, filterlink2));
URL_Can.Remove(tempURL);
richTextBox2.PerformSafely(() => richTextBox2.AppendText(tempURL + "\n"));
}
}
toAvoidLoopinLinks = tempURL;
}
Thanks for All, I managed to solve this issue using Dictionary instead of Hashset, and use the Key to hold the URL , and the value to hold int , to be 1 if the urls is scanned , or 0 if the url still not processed, below is my code.
I used another Dictionary "URL_CANtoSave to hold the url that ends with jpg "my target"...and this loop of While..can loop until all the url of the website ran out based on the values you specify in the filter string variable that you parse the urls accordingly.
so to break the loop you can specify amount of images url to get in the URL_CantoSave.
return Task.Factory.StartNew(() =>
{
try
{
string tempURL;
int i = 0;
// I used to set the value of Dictionary Key, 1 or 0 ( 1 means scanned,
0 means not yet and to iterate until all the Dictionry Keys are scanned or you break in the middle based on how much images urls you collected in the other Dictionary
while (URL_Can.Values.Where(value => value.Equals(0)).Any())
{
// take 1 key and put it in temp variable
tempURL = URL_Can.ElementAt(i).Key;
// check if it ends with your target file extension. in this case image file
if (tempURL.EndsWith("jpg"))
{
URL_CanToSave.Add(tempURL,0);
URL_Can.Remove(tempURL);
}
// if not image go and download the page based on the url and keep analyzing
else
{
// if the url not scanned before then
if (URL_Can[tempURL] != 1)
{
// here it seems complex little bit, where Add2Dic is process to add to Dictionaries without adding the Key again ( solving main problem !! )
"ExtractURLfromLink" is another process that return dictionary with all links analyzed by downloading the document string of the url and analyzing it ,
you can add remove filter string based on you analysis
Add2Dic(ExtractUrlsfromLink(client, tempURL, filterlink1), URL_Can, false);
Add2Dic(ExtractUrlsfromLink(client, tempURL, filterlink2), URL_Can, false);
URL_Can[tempURL] = 1; // to set it as scanned link
richTextBox2.PerformSafely(() => richTextBox2.AppendText(tempURL + "\n"));
}
}
statusStrip1.PerformSafely(() => toolStripProgressBar1.PerformStep());
// here comes the other trick to keep this iteration keeps going until it scans all gathered links
i++; if (i >= URL_Can.Count) { i = 0; }
if (URL_CanToSave.Count >= 150) { break; }
}
richTextBox2.PerformSafely(() => richTextBox2.Clear());
textBox1.PerformSafely(() => textBox1.Text = URL_Can.Count.ToString());
return ProcessCompleted = true;
}
catch (Exception aih)
{
MessageBox.Show(aih.Message);
return ProcessCompleted = false;
throw;
}
{
richTextBox2.PerformSafely(()=>richTextBox2.AppendText(url+"\n"));
}
})

When I try to read an X12 204 using EDI Fabric, I get "Invalid Node Name: ST", but the file is well formed. Any idea why?

Here's an example 204 I have made. It validates with a couple different validation tools (EDI Notepad and Altova), but when I try to use EDI fabric to parse it, it gets the ISA and GS data just fine, but then errors out with "Invalid Node Name: ST".
I can't figure out why, any ideas?
ISA*ZZ* *ZZ* *ZZ*XXXX *ZZ*YYYY *170130*1025*U*00401*485789958*0*P*~
GS*SM*YYYY*XXXX*20170130*1027*485790079*X*004010
ST*204*485790093
B2**YYYY**123456789**CC
B2A*00
L11*123456789*CR
S5*1*LD
G62*64*20160131*1*1351
SE*7*485790093
GE*1*485790079
IEA*1*485789958
Here is the code:
internal static void Parse204(FileStream file,
List<MyCompany.TruckRouteInfo> result)
{
var reader = EdiFabric.Framework.Readers.X12Reader.Create(file);
file.Flush();
var qEdiItems = reader.ReadToEnd();
var ediItems = qEdiItems.ToList();
var m204 = ediItems.OfType<M_204>().ToList();
foreach (var item in m204)
{
MyCompany.TruckRouteInfo stop = new MyCompany.TruckRouteInfo ();
foreach (var l11 in item.S_L11)
{
if (l11.D_128_2 == EdiFabric.Rules.X12004010204.X12_ID_128.CR)
{
stop.Reference1 = l11.D_127_1;
}
}
result.Add(stop);
}
}
I've just literally copied your example and pasted it to a file which was processed fine. Works on my machine :)
My best guess would be to open the file and inspect the line terminators for any discrepancies, which might have been sorted when I copied it\pasted it.

Unable to figure out how to use post method, for a suitescript written in Netsuite

I am trying to do use the post method for a simple suitescript program, i am very new to this.
In Netsuite i have written a suitescript as follows.
function restPost()
{
var i = nlapiLoadRecord('department', 115);
var memo = nlapisetfieldvalue('custrecord225', ' ');// this is a customfield, which i want to populate the memo field, using rest client in firefox
var recordId = nlapiSubmitRecord(i);
}
i have created a script record and uploaded this suitescript and even copied the external URL to paste it in restclient.
In Restclient(firefox plugin), pasted the external URL, i have given the method as post, header authorization given, content-type: application/json, and in body i put in {"memo":"mynamehere"};
In this the error i get is
message": "missing ) after argument list
I even tried it by writting other suitescript programs the errors i get is as follows:
Unexpected token in object literal (null$lib#3) Empty JSON string
Invalid data format. You should return TEXT.
I am kinda new to the programming world, so any help would be really good.
I think you are trying to create a RESTlet for POST method. Following is the sample code for POST method -
function createRecord(datain)
{
var err = new Object();
// Validate if mandatory record type is set in the request
if (!datain.recordtype)
{
err.status = "failed";
err.message= "missing recordtype";
return err;
}
var record = nlapiCreateRecord(datain.recordtype);
for (var fieldname in datain)
{
if (datain.hasOwnProperty(fieldname))
{
if (fieldname != 'recordtype' && fieldname != 'id')
{
var value = datain[fieldname];
if (value && typeof value != 'object') // ignore other type of parameters
{
record.setFieldValue(fieldname, value);
}
}
}
}
var recordId = nlapiSubmitRecord(record);
nlapiLogExecution('DEBUG','id='+recordId);
var nlobj = nlapiLoadRecord(datain.recordtype,recordId);
return nlobj;
}
So after deploying this RESTlet you can call this POST method by passing following sample JSON payload -
{"recordtype":"customer","entityid":"John Doe","companyname":"ABCTools Inc","subsidiary":"1","email":"jdoe#email.com"}
For Authorization you have to pass request headers as follows -
var headers = {
"Authorization": "NLAuth nlauth_account=" + cred.account + ", nlauth_email=" + cred.email +
", nlauth_signature= " + cred.password + ", nlauth_role=" + cred.role,
"Content-Type": "application/json"};
I can understand your requirement and the answer posted by Parsun & NetSuite-Expert is good. You can follow that code. That is a generic code that can accept any master record without child records. For Example Customer Without Contact or Addressbook.
I would like to suggest a small change in the code and i have given it in my solution.
Changes Below
var isExistRec = isExistingRecord(objDataIn);
var record = (isExistRec) ? nlapiLoadRecord(objDataIn.recordtype, objDataIn.internalid, {
recordmode: 'dynamic'
}) : nlapiCreateRecord(objDataIn.recordtype);
//Check for Record is Existing in Netsuite or Not using a custom function
function isExistingRecord(objDataIn) {
if (objDataIn.internalid != null && objDataIn.internalid != '' && objDataIn.internalid.trim().length > 0)
return true;
else
return false;
}
So whenever you pass JSON data to the REStlet, keep in mind you have
to pass the internalid, recordtype as mandatory values.
Thanks
Frederick
I believe you will want to return something from your function. An empty object should do fine, or something like {success : true}.
Welcome to Netsuite Suitescripting #Vin :)
I strongly recommend to go through SuiteScript API Overview & SuiteScript API - Alphabetized Index in NS help Center, which is the only and most obvious place to learn the basics of Suitescripting.
nlapiLoadRecord(type, id, initializeValues)
Loads an existing record from the system and returns an nlobjRecord object containing all the field data for that record. You can then extract the desired information from the loaded record using the methods available on the returned record object. This API is a core API. It is available in both client and server contexts.
function restPost(dataIn) {
var record = nlapiLoadRecord('department', 115); // returns nlobjRecord
record.setFieldValue('custrecord225', dataIn.memo); // set the value in custom field
var recordId = nlapiSubmitRecord(record);
return recordId;
}

neo4j 2.0 findNodesByLabelAndProperty not working

I'm currently trying the Neo4j 2.0.0 M3 and see some strange behaviour. In my unit tests, everything works as expected (using an newImpermanentDatabase) but in the real thing, I do not get results from the graphDatabaseService.findNodesByLabelAndProperty.
Here is the code in question:
ResourceIterator<Node> iterator = graphDB
.findNodesByLabelAndProperty(Labels.User, "EMAIL_ADDRESS", emailAddress)
.iterator();
try {
if (iterator.hasNext()) { // => returns false**
return iterator.next();
}
} finally {
iterator.close();
}
return null;
This returns no results. However, when running the following code, I see my node is there (The MATCH!!!!!!!!! is printed) and I also have an index setup via the schema (although that if I read the API, this seems not necessary but is important for performance):
ResourceIterator<Node> iterator1 = GlobalGraphOperations.at(graphDB).getAllNodesWithLabel(Labels.User).iterator();
while (iterator1.hasNext()) {
Node result = iterator1.next();
UserDao.printoutNode(emailAddress, result);
}
And UserDao.printoutNode
public static void printoutNode(String emailAddress, Node next) {
System.out.print(next);
ResourceIterator<Label> iterator1 = next.getLabels().iterator();
System.out.print("(");
while (iterator1.hasNext()) {
System.out.print(iterator1.next().name());
}
System.out.print("): ");
for(String key : next.getPropertyKeys()) {
System.out.print(key + ": " + next.getProperty(key).toString() + "; ");
if(emailAddress.equals( next.getProperty(key).toString())) {
System.out.print("MATCH!!!!!!!!!");
}
}
System.out.println();
}
I already debugged through the code and what I already found out is that I pass via the InternalAbstractGraphDatabase.map2Nodes to a DelegatingIndexProxy.getDelegate and end up in IndexReader.Empty class which returns the IteratorUtil.EMPTY_ITERATOR thus getting false for iterator.hasNext()
Any idea's what I am doing wrong?
Found it:
I only included neo4j-kernel:2.0.0-M03 in the classpath. The moment I added neo4j-cypher:2.0.0-M03 all was working well.
Hope this answer helps save some time for other users.
#Neo4j: would be nice if an exception would be thrown instead of just returning nothing.
#Ricardo: I wanted to but I was not allowed yet as my reputation wasn't good enough as a new SO user.

Resources