Logger.h
enum ChannelType {
main_channel,
sub_channel
};
BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", ChannelType)
class Logger {
public:
enum severity_level
{
debug,
info,
warning,
error,
fatal
};
static void init(Logger::severity_level level);
typedef boost::log::sources::severity_channel_logger< Logger::severity_level, ChannelType > logger_type;
static thread_local logger_type gl;
static thread_local logger_type motion_checker;
};
Logger.cpp
void Logger::init(Logger::severity_level level)
{
boost::shared_ptr<boost::log::core> core = boost::log::core::get();
core->set_exception_handler(boost::log::make_exception_suppressor());
core->set_filter(boost::log::expressions::attr<Logger::severity_level>("Severity") >= level);
{
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_multifile_backend> multifile_sink;
boost::shared_ptr<multifile_sink> sink(new multifile_sink);
sink->locked_backend()->set_file_name_composer(boost::log::sinks::file::as_file_name_composer(
boost::log::expressions::stream << "./log/Sub/" << boost::log::expressions::attr< std::string >("RoleName") << ".log"));
sink->set_formatter
(
boost::log::expressions::format("[%1%] - %2%")
% boost::log::expressions::attr< boost::posix_time::ptime >("TimeStamp")
% boost::log::expressions::smessage
);
sink->set_filter(channel == sub_channel);
core->add_sink(sink);
}
//============use add_file_log==============
boost::log::add_file_log(
boost::log::keywords::filter = channel == main_channel,
boost::log::keywords::file_name = "./log/%Y%m%d.log",
boost::log::keywords::auto_flush = true,
boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
boost::log::keywords::format = "[%TimeStamp%] (%LineID%) {%ThreadID%}: %Message%"
);
//==================use add_file_log end====================
//=========manually add sink, this has problem================
boost::shared_ptr< boost::log::sinks::text_file_backend > backend =
boost::make_shared< boost::log::sinks::text_file_backend >(
boost::log::keywords::filter = channel == main_channel,
boost::log::keywords::file_name = "./log/%Y%m%d.log",
boost::log::keywords::auto_flush = true,
boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
boost::log::keywords::format = "[%TimeStamp%] (%LineID%) {%ThreadID%}: %Message%"
);
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend> file_sink;
boost::shared_ptr< file_sink > sink(new file_sink(backend));
core->add_sink(sink);
//============manually add end==========================
boost::log::add_common_attributes();
}
thread_local Logger::logger_type Logger::gl(boost::log::keywords::channel = main_channel);
thread_local Logger::logger_type Logger::motion_checker(boost::log::keywords::channel = sub_channel);
main.cpp
int main()
{
Logger::init(Logger::debug);
BOOST_LOG_SEV(Logger::gl, Logger::debug) << "ssss";
{
BOOST_LOG_SCOPED_LOGGER_ATTR(Logger::motion_checker, "RoleName", boost::log::attributes::constant< std::string >("aaa"))
BOOST_LOG_SEV(Logger::motion_checker, Logger::debug) << "aaaa";
}
system("pause");
return 0;
}
Using add_file_log, every thing is OK, but the manually add sink lost all attributes, only message in there. And the filter is also not work, sub_channel message will add to this file. The reason I create this file sink manually is because add_file_log create sync sink, I want a async sink.
The problem is that the named parameters format and filter are used by the sink frontend, not the backend, and you pass them to the backend. As a result neither filter nor formatter are set.
I suggest you move all named parameters to the sink frontend constructor and let it pass the parameters to the backend constructor instead of constructing the backend yourself.
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend> file_sink;
boost::shared_ptr< file_sink > sink = boost::make_shared< file_sink >(
boost::log::keywords::filter = channel == main_channel,
boost::log::keywords::file_name = "./log/%Y%m%d.log",
boost::log::keywords::auto_flush = true,
boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
boost::log::keywords::format = "[%TimeStamp%] (%LineID%) {%ThreadID%}: %Message%"
);
core->add_sink(sink);
Related
I am trying to deserialize an array of chars using the ArduinoJson Lib. The chars are coming from a I2C connection using Wire library. They come successfully so I don't think there is an issue there.
When trying to de-serialize at run time I get the message "deserializeJson() failed: EmptyInput".
From ArduinoJson Troubleshooter's report
The issue happens at run time
The issue concerns deserialization
deserializeJson() returns EmptyInput
Input comes neither from an HTTP response, nor a file, nor a stream
The part of code that deserialization fails is here:
void callback(char payload[], unsigned int msg_size) {
Serial.print("Message arrived ");
for (int i=0;i<msg_size;i++) {
Serial.print((payload[i]));
}
DeserializationError error = deserializeJson(doc, payload, msg_size);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
const char* command = doc["cmd"];
Serial.print("command ");
Serial.println(command);
//rest of code
}
void setup() {
//communications
Wire.begin(0x8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
Serial.print("Start_");
Serial.println(ver);
}
void loop() {
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
char buff[60];
Serial.print("how many=");
Serial.println(howMany);
//initialize buffers
buff[0] = '\0';
int i = 0;
while (0 < Wire.available()) { // loop through all but the last
//char c = Wire.read(); // receive byte as a character
char c = Wire.read();
Serial.print(c); // print the character
buff[i] = c;
buff[i+1] = '\0'; // Add a NULL after each character
i++;
}
int x = Wire.read(); // receive byte as an integer
Serial.println();
Serial.print("x:");
Serial.println(x); // print the integer
Serial.print("BUFFER:");
for (int j=0; j < howMany; j++) {
Serial.print(buff[j]);
}
Serial.println();
Serial.print("size:");
Serial.println(sizeof(buff));
callback(buff, howMany);
}
The print out from serial ide is here:
Start_v.0.1
how many=25
{"cmd":"demo","seq":"1"}
x:-1
BUFFER:{"cmd":"demo","seq":"1"}
size:60
Message arrived {"cmd":"demo","seq":"1"} deserializeJson() failed: EmptyInput
But the payload variable, as you see here is not empty.
Can you provide any debugging hints? Thank you
Edit: I have added more code that shows the i2c communication
from smbus import SMBus
addr = 0x8 # bus address
bus = SMBus(1) # indicates /dev/ic2-1
numb = 1
def StringToBytes(val):
retVal = []
for c in val:
retVal.append(ord(c))
return retVal
def writeData(arrayValue, i2c_address):
byteValue = StringToBytes(arrayValue)
# examples --->
bus.write_i2c_block_data(i2c_address,0x00,byteValue)
return -1
# main
print ("Enter command:")
while 1:
cmd = input(">>>> ")
writeData(str(cmd), addr)
I filtered the incoming i2c buffer for nulls and the de serialization of JSON worked. I am not sure why the nulls are sent by rpi/python.
void receiveEvent(int howMany) {
char buff[60];
Serial.print("how many=");
Serial.println(howMany);
//initialize buffers
buff[0] = '\0';
int i = 0;
while (0 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
if (c == '\0') {
//ignore
} else {
//char c = Wire.read();
Serial.print(c); // print the character
buff[i] = c;
buff[i+1] = '\0'; // Add a NULL after each character
i++;
}
}
int x = Wire.read(); // receive byte as an integer
Serial.println();
Serial.print("x:");
Serial.println(x); // print the integer
Serial.print("BUFFER:");
for (int j=0; j < howMany; j++) {
Serial.print(buff[j]);
}
Serial.println();
Serial.print("size:");
Serial.println(sizeof(buff));
callback(buff, howMany);
}
This is my first time using Arduino IDE, and after replacing the jsonBuffer with jsonDOcument, as jsonBuffer was an older version, instructed by the jsonarduino website, and i have received the error message, "no matching function for call to 'ArduinoJson6171_91::BasicJsonDocument<ArduinoJson6171_91::DefaultAllocator>::BasicJsonDocument()'"
What should I do?
This is my code:
#include <FS.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <RCSwitch.h>
#include <WiFiUdp.h>
#include <WiFiManager.h>
#include <ArduinoJson.h>
#include
#ifndef CALLBACKFUNCTION_H //this is the beginning of the callbackfunction script
#define CALLBACKFUNCTION_H
#include <Arduino.h>
typedef void (*CallbackFunction) ();
#endif //this is the end of the callbackfunction script
#ifndef SWITCH_H //this is the beginning of the switch script
#define SWITCH_H
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiUDP.h>
#include "CallbackFunction.h"
class Switch {
private:
ESP8266WebServer *server = NULL;
WiFiUDP UDP;
String serial;
String persistent_uuid;
String device_name;
unsigned int localPort;
CallbackFunction onCallback;
CallbackFunction offCallback;
void startWebServer();
void handleEventservice();
void handleUpnpControl();
void handleRoot();
void handleSetupXml();
public:
Switch();
Switch(String alexaInvokeName, unsigned int port, CallbackFunction onCallback, CallbackFunction offCallback);
~Switch();
String getAlexaInvokeName();
void serverLoop();
void respondToSearch(IPAddress& senderIP, unsigned int senderPort);
};
#endif //this is the end of the switch script
#include "switch.h"
#include "UpnpBroadcastResponder.h"
#include "CallbackFunction.h"
UpnpBroadcastResponder upnpBroadcastResponder;
Switch *alexa_switch1 = NULL;
Switch *alexa_switch2 = NULL;
Switch *alexa_switch3 = NULL;
Switch *alexa_switch4 = NULL;
Switch *alexa_switch5 = NULL;
// Callback prototypes
void alexa_switch1On();
void alexa_switch1Off();
void alexa_switch2On();
void alexa_switch2Off();
void alexa_switch3On();
void alexa_switch3Off();
void alexa_switch4On();
void alexa_switch4Off();
void alexa_switch5On();
void alexa_switch5Off();
// Set Relay Pins
int relayOne = 12;
int relayTwo = 13;
int relayThree = 14;
int relayFour = 16;
// Names each relay/outlet/device is known by -- these are set during config
char alexa_name1[100] = "1";
char alexa_name2[100] = "2";
char alexa_name3[100] = "3";
char alexa_name4[100] = "4";
char alexa_name5[100] = "5";
const char* AP_Name = "EchoBase1";
char saved_ssid[100] = "";
char saved_psk[100] = "";
// Flag for saving config data
bool shouldSaveConfig = false;
bool forceConfigPortal = false;
WiFiManager wifiManager;
// RF Tooling - https://codebender.cc/sketch:80290#RCSwitch%20-%20Transmit%20(Etekcity%20Power%20Outlets).ino
RCSwitch RFSwitch = RCSwitch();
int RF_PULSE_LENGTH = 179; // Pulse length to use for RF transmitter
int RF_TX_PIN = 0; // Digital pin connected to RF transmitter
int RF_BIT_LENGTH = 24;
// RF Signals (varies per remote controlled plugin set)
unsigned long rc_codes[5][2] = {
// ON //OFF
{5313843, 5313852}, /* Outlet 1 /
{5313987, 5313996}, / Outlet 2 /
{5314307, 5314316}, / Outlet 3 /
{335107, 335116}, / Outlet 4 /
{341251, 341260}, / Outlet 5 */
};
// Callback notifying us of the need to save config
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;
}
void setup()
{
Serial.begin(115200);
// -- WifiManager handling
// 5-second delay in case you wish to observe boot-up
for(int i=0; i < 5; i++) {
Serial.print(".");
delay(1000);
}
Serial.println("Booting");
// Clean FS, for testing... consider enabling if jumper is in flash mode, etc.
// SPIFFS.format();
// Set the flash/boot pin for input so we can read if the jumper is present
pinMode(0, INPUT);
// If the jumper is in "flash" mode (i.e., pin 0 is grounded), we will be enabling the config portal
forceConfigPortal = (digitalRead(0) == 0);
if(forceConfigPortal) {
Serial.println("Jumper set for flash - will trigger config portal");
} else {
Serial.println("Jumper set for boot - will attempt autoconnect, else config portal");
}
// Read configuration from FS json
Serial.println("Mounting ESP8266 integrated filesystem...");
if (SPIFFS.begin()) {
Serial.println("Mounted file system");
if (SPIFFS.exists("/config.json")) {
Serial.println("Found existing config; reading file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("Opened config file for reading");
size_t size = configFile.size();
Serial.print("File size (bytes) = ");
Serial.println(size);
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonDocument jsonDocument;
JsonObject& json = jsonDocument.parseObject(buf.get());
Serial.println("Parsed JSON content:");
json.printTo(Serial);
Serial.println();
if (json.success()) {
strcpy(alexa_name1, json["alexa_name1"]);
strcpy(alexa_name2, json["alexa_name2"]);
strcpy(alexa_name3, json["alexa_name3"]);
strcpy(alexa_name4, json["alexa_name4"]);
strcpy(alexa_name5, json["alexa_name5"]);
Serial.println("Parsed Alexa relay name #1: " + String(alexa_name1));
Serial.println("Parsed Alexa relay name #2: " + String(alexa_name2));
Serial.println("Parsed Alexa relay name CharlesJGantt#3: " + String(alexa_name3));
Serial.println("Parsed Alexa relay name CharlesJGantt#4: " + String(alexa_name4));
Serial.println("Parsed Alexa relay name CharlesJGantt#5: " + String(alexa_name5));
} else {
Serial.println("** ERROR ** Failed to load/parse JSON config");
}
} else {
Serial.println("No JSON file found in filesystem");
}
}
} else {
Serial.println("** ERROR ** Failed to mount ESP8266's integrated filesyste,m");
}
// The extra parameters to be configured (can be either global or just in the setup)
// After connecting, parameter.getValue() will get you the configured value
// id/name placeholder/prompt default length
WiFiManagerParameter custom_alexa_name1("alexa_name1", "Device #1 name", alexa_name1, 100);
WiFiManagerParameter custom_alexa_name2("alexa_name2", "Device #2 name", alexa_name2, 100);
WiFiManagerParameter custom_alexa_name3("alexa_name3", "Device CharlesJGantt#3 name", alexa_name3, 100);
WiFiManagerParameter custom_alexa_name4("alexa_name4", "Device CharlesJGantt#4 name", alexa_name4, 100);
WiFiManagerParameter custom_alexa_name5("alexa_name5", "Device CharlesJGantt#5 name", alexa_name5, 100);
// Set the function that will be called to save the custom parameter after config
wifiManager.setSaveConfigCallback(saveConfigCallback);
// Hand the parameter defintions to the WifiManager for use during config
wifiManager.addParameter(&custom_alexa_name1);
wifiManager.addParameter(&custom_alexa_name2);
wifiManager.addParameter(&custom_alexa_name3);
wifiManager.addParameter(&custom_alexa_name4);
wifiManager.addParameter(&custom_alexa_name5);
//reset settings - for testing
//wifiManager.resetSettings();
//set minimu quality of signal so it ignores AP's under that quality
//defaults to 8%
//wifiManager.setMinimumSignalQuality();
//sets timeout until configuration portal gets turned off
//useful to make it all retry or go to sleep
//in seconds
//wifiManager.setTimeout(120);
if(forceConfigPortal) {
wifiManager.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
// Force config portal while jumper is set for flashing
if (!wifiManager.startConfigPortal(AP_Name)) {
Serial.println("** ERROR ** Failed to connect with new config / possibly hit config portal timeout; Resetting in 3sec...");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
} else {
// Autoconnect if we can
// Fetches ssid and pass and tries to connect; if it does not connect it starts an access point with the specified name
// and goes into a blocking loop awaiting configuration
if (!wifiManager.autoConnect(AP_Name)) {
Serial.println("** ERROR ** Failed to connect with new config / possibly hit timeout; Resetting in 3sec...");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
}
// --- If you get here you have connected to the WiFi ---
Serial.println("Connected to wifi");
// Save the connect info in case we need to reconnect
WiFi.SSID().toCharArray(saved_ssid, 100);
WiFi.psk().toCharArray(saved_psk, 100);
// Read updated parameters
strcpy(alexa_name1, custom_alexa_name1.getValue());
strcpy(alexa_name2, custom_alexa_name2.getValue());
strcpy(alexa_name3, custom_alexa_name3.getValue());
strcpy(alexa_name4, custom_alexa_name4.getValue());
strcpy(alexa_name5, custom_alexa_name5.getValue());
Serial.println("Read configured Alexa relay name #1: " + String(alexa_name1));
Serial.println("Read configured Alexa relay name #2: " + String(alexa_name2));
Serial.println("Read configured Alexa relay name CharlesJGantt#3: " + String(alexa_name3));
Serial.println("Read configured Alexa relay name CharlesJGantt#4: " + String(alexa_name4));
Serial.println("Read configured Alexa relay name CharlesJGantt#5: " + String(alexa_name5));
// Save the custom parameters to the ESP8266 filesystem if changed
if (shouldSaveConfig) {
Serial.println("Saving config to ESP8266 filesystem");
DynamicJsonDocument jsonDocument;
JsonObject& json = jsonDocument.createObject();
json["alexa_name1"] = alexa_name1;
json["alexa_name2"] = alexa_name2;
json["alexa_name3"] = alexa_name3;
json["alexa_name4"] = alexa_name4;
json["alexa_name5"] = alexa_name5;
Serial.println("Attempting to open config JSON file for writing");
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("** ERROR ** Failed to open JSON config file for writing");
} else {
json.printTo(Serial);
Serial.println();
json.printTo(configFile);
configFile.close();
Serial.println("File write complete");
}
}
Serial.print("SSID: " );
Serial.println(WiFi.SSID());
Serial.print("Local IP: ");
Serial.println(WiFi.localIP());
// -- ALEXA setup/handling --
upnpBroadcastResponder.beginUdpMulticast();
// Define your switches here. Max 14
// Format: Alexa invocation name, local port no, on callback, off callback
alexa_switch1 = new Switch(alexa_name1, 80, alexa_switch1On, alexa_switch1Off);
alexa_switch2 = new Switch(alexa_name2, 81, alexa_switch2On, alexa_switch2Off);
alexa_switch3 = new Switch(alexa_name3, 82, alexa_switch3On, alexa_switch3Off);
alexa_switch4 = new Switch(alexa_name4, 83, alexa_switch4On, alexa_switch4Off);
alexa_switch5 = new Switch(alexa_name5, 85, alexa_switch5On, alexa_switch5Off);
Serial.println("Adding switches upnp broadcast responder");
upnpBroadcastResponder.addDevice(*alexa_switch1);
upnpBroadcastResponder.addDevice(*alexa_switch2);
upnpBroadcastResponder.addDevice(*alexa_switch3);
upnpBroadcastResponder.addDevice(*alexa_switch4);
upnpBroadcastResponder.addDevice(*alexa_switch5);
// Setup RF Transmitter
RFSwitch.enableTransmit(RF_TX_PIN);
RFSwitch.setPulseLength(RF_PULSE_LENGTH);
}
/* If disconnected from Wifi, enter a blocking loop that periodically attempts reconnection */
void reconnectIfNecessary() {
while(WiFi.status() != WL_CONNECTED) {
Serial.println("Disconnected; Attempting reconnect to " + String(saved_ssid) + "...");
WiFi.disconnect();
WiFi.mode(WIFI_AP_STA);
WiFi.begin(saved_ssid, saved_psk);
// Output reconnection status info every second over the next 10 sec
for( int i = 0; i < 10 ; i++ ) {
delay(1000);
Serial.print("WiFi status = ");
if( WiFi.status() == WL_CONNECTED ) {
Serial.println("Connected");
break;
} else {
Serial.println("Disconnected");
}
}
if(WiFi.status() != WL_CONNECTED) {
Serial.println("Failure to establish connection after 10 sec. Will reattempt connection in 2 sec");
delay(2000);
}
}
}
void loop()
{
// Ensure wifi is connected (won't return until it has connected)
reconnectIfNecessary();
// Respond to any Alexa/discovery requests
upnpBroadcastResponder.serverLoop();
// Respond to any UPnP control requests
alexa_switch1->serverLoop();
alexa_switch2->serverLoop();
alexa_switch3->serverLoop();
alexa_switch4->serverLoop();
alexa_switch5->serverLoop();
}
void alexa_switch1On() {
Serial.println("Switch 1 turn on ...");
enableOutlet(1, true);
}
void alexa_switch1Off() {
Serial.println("Switch 1 turn off ...");
enableOutlet(1, false);
}
void alexa_switch2On() {
Serial.println("Switch 2 turn on ...");
enableOutlet(2, true);
}
void alexa_switch2Off() {
Serial.println("Switch 2 turn off ...");
enableOutlet(2, false);
}
void alexa_switch3On() {
Serial.println("Switch 3 turn on ...");
enableOutlet(3, true);
}
void alexa_switch3Off() {
Serial.println("Switch 3 turn off ...");
enableOutlet(3, false);
}
void alexa_switch4On() {
Serial.println("Switch 4 turn on ...");
enableOutlet(4, true);
}
void alexa_switch4Off() {
Serial.println("Switch 4 turn off ...");
enableOutlet(4, false);
}
void alexa_switch5On() {
Serial.println("Switch 5 turn on ...");
enableOutlet(5, true);
}
void alexa_switch5Off() {
Serial.println("Switch 5 turn off ...");
enableOutlet(5, false);
}
void enableOutlet(int outletNumber, bool onOrOff)
{
if (outletNumber < 1 || outletNumber > 5) {
Serial.println("Invalid outlet number");
return;
}
unsigned long *onOffCodes = rc_codes[outletNumber - 1];
unsigned long codeToSend = onOffCodes[onOrOff ? 0 : 1];
RFSwitch.send(codeToSend, RF_BIT_LENGTH);
char outletNumberString[1];
int retVal = snprintf(outletNumberString, 1, "%d", outletNumber);
if (retVal < 0) {
Serial.println("Log encoding error");
return;
}
Serial.print("Switch " + String(outletNumber) + " turned ");
if (onOrOff) {
Serial.println("on");
} else {
Serial.println("off");
}
}
My environment:
RadStudio 10.2 Tokyo
Working on Windows 10 (64bit) v1809
I was searching the way to replace JSON value.
Then, I came across the following Q and A.
Delphi XE7: How to change a JSON value using System.JSON (versus SuperObject)
In Delphi:
JoPair.JsonValue.Free;
JoPair.JsonValue := TJSONNumber.Create(123);
Following this, I thought, it would be in C++ Builder
JoPair->JsonValue->Free();
JoPair->JsonValue = new TJSONNumber(123);
However, it caused "access violation" error in ToString();
Instead, I commented out JoPair->JsonValue->Free();, then no problem.
Question:
In C++ Buidler, should I need Free JoPair->JsonValue?
But without Freeing the JsonValue, it may cause memory leak.
source code
Following is the actual code I checked
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <DBXJSON.hpp> // for JSON
#include <memory> // for unique_ptr
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String srcFileName = L"test.json"; // source
String dstFileName = L"out.json"; // destination
String targetKeySubString = L"hogehoge"; //
String targetValue = "9";
// 1. read JSON strings
std::unique_ptr<TStringList> slread(new TStringList);
slread->LoadFromFile(srcFileName);
// 2. replace values for the key (target is checked by substring)
TJSONObject *jsonObj;
String jsonKey, jsonValue;
TJSONPair *pairObj;
std::unique_ptr<TStringList> slwrite(new TStringList);
for(int li=0; li < slread->Count; li++) { // file line index
String jsonText = slread->Strings[li];
// this is needed for avoiding error caused by the file path treating backslash
jsonText = StringReplace(jsonText, L"\\", L"\\\\", TReplaceFlags()<<rfReplaceAll);
//
jsonObj = dynamic_cast<TJSONObject*>(TJSONObject::ParseJSONValue(jsonText));
for(int pi=0; pi < jsonObj->Size(); pi++) { // pair index
pairObj = jsonObj->Get(pi);
jsonKey = pairObj->JsonString->Value();
jsonValue = pairObj->JsonValue->Value();
if (jsonKey.Pos(targetKeySubString) == 0) {
continue;
}
// replace value
// (ref: https://stackoverflow.com/questions/33426576/delphi-xe7-how-to-change-a-json-value-using-system-json-versus-superobject)
//
//pairObj->JsonValue->Free(); // commented out because this causes "access violation" in ToString()
pairObj->JsonValue = new TJSONString(targetValue);
// debug
//ShowMessage(jsonKey + ":" + jsonValue);
}
slwrite->Add(jsonObj->ToString());
}
jsonObj->Free();
// 3. output
slwrite->SaveToFile(dstFileName);
ShowMessage(L"Done");
}
//---------------------------------------------------------------------------
Example
{"1_hogehoge":"3", "2_fugafuga":"1","3_hogehoge":"4", "4_fugafuga":"1", "5_hogehoge":"5", "6_fugafuga":"9"}
{"1_hogehoge":"9","2_fugafuga":"1","3_hogehoge":"9","4_fugafuga":"1","5_hogehoge":"9","6_fugafuga":"9"}
Source code (10.2 Tokyo)
I have updated the source code. Still same problem.
I also used ToJSON() instead of ToString() with same error (access violation)`.
I also tried using std::unique_ptr, which caused another error. So I gave up using std::unique_ptr on this topic now (may better be investigated separately).
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <System.JSON.hpp>
#include <memory> // for unique_ptr
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String srcFileName = L"test.json"; // source
String dstFileName = L"out.json"; // destination
String targetKeySubString = L"hogehoge"; //
String targetValue = "9";
// 1. read JSON strings
std::unique_ptr<TStringList> slread(new TStringList);
slread->LoadFromFile(srcFileName);
// 2. replace values for the key (target is checked by substring)
TJSONObject *jsonObj;
//std::unique_ptr<TJSONObject> jsonObj(new TJSONObject);
String jsonKey, jsonValue;
TJSONPair *pairObj;
std::unique_ptr<TStringList> slwrite(new TStringList);
for(int li=0; li < slread->Count; li++) { // file line index
String jsonText = slread->Strings[li];
// this is needed for avoiding error caused by the file path treating backslash
jsonText = StringReplace(jsonText, L"\\", L"\\\\", TReplaceFlags()<<rfReplaceAll);
//
jsonObj = dynamic_cast<TJSONObject*>(TJSONObject::ParseJSONValue(jsonText));
if (jsonObj == NULL) {
continue;
}
for(int pi=0; pi < jsonObj->Count; pi++) { // pair index
pairObj = jsonObj->Pairs[pi];
jsonKey = pairObj->JsonString->Value();
jsonValue = pairObj->JsonValue->Value();
if (jsonKey.Pos(targetKeySubString) == 0) {
continue;
}
// replace value
// (ref: https://stackoverflow.com/questions/33426576/delphi-xe7-how-to-change-a-json-value-using-system-json-versus-superobject)
//
//pairObj->JsonValue->Free(); // commented out because this causes "access violation" in ToString()
delete pairObj->JsonValue;
pairObj->JsonValue = new TJSONString(targetValue);
// debug
//ShowMessage(jsonKey + ":" + jsonValue);
}
//String res = jsonObj->ToJSON(); // *** access violation ***
String res = jsonObj->ToString(); // *** access violation ***
slwrite->Add(res);
jsonObj->Free();
}
// 3. output
slwrite->SaveToFile(dstFileName);
ShowMessage(L"Done");
}
//---------------------------------------------------------------------------
I am working on an implementation to generate alternate Paths using via node method.
While checking for local optimality I do the following
forwardEdge = bestWeightMapFrom.get(viaNode);
reverseEdge = bestWeightMapTo.get(viaNode);
double unpackedUntilDistance = 0;
while(forwardEdge.edge != -1) {
double parentDist = forwardEdge.parent != null ? forwardEdge.parent.distance : 0;
double dist = forwardEdge.distance - parentDist;
if(unpackedUntilDistance + dist >= T_THRESHOLD) {
EdgeSkipIterState edgeState = (EdgeSkipIterState) graph.getEdgeProps(forwardEdge.edge, forwardEdge.adjNode);
unpackStack.add(new EdgePair(edgeState, false));
sV = forwardEdge.adjNode;
forwardEdge = forwardEdge.parent;
break;
}
else {
unpackedUntilDistance += dist;
forwardEdge = forwardEdge.parent;
sV = forwardEdge.adjNode;
}
}
int oldSV = forwardEdge.adjNode;
EdgeEntry oldForwardEdge = forwardEdge;
I unpack the edge in the stack to further narrow down sV.
I get vT and oldVt in a similar fashion by traversing reverseEdge.
if I determine that the path from sV and vT is <= length of unpacked edges I accept this via node and construct the alternatePath as follows.
PathBidirRef p = (PathBidirRef) algo.calcPath(oldSV, oldVT);
Path4CHAlt p1 = new Path4CHAlt(graph, flagEncoder);
p1.setSwitchToFrom(false);
p1.setEdgeEntry(oldForwardEdge);
p1.segmentEdgeEntry = p.edgeEntry;
double weight = oldForwardEdge.weight + oldReverseEdge.weight + p.edgeEntry.weight + p.edgeTo.weight;
p1.setWeight(weight);
p1.edgeTo = oldReverseEdge;
p1.segmentEdgeTo = p.edgeTo;
Path p2 = p1.extract();
Path4CHAlt is
public class Path4CHAlt extends Path4CH {
private boolean switchWrapper = false;
public EdgeEntry segmentEdgeTo;
public EdgeEntry segmentEdgeEntry;
public Path4CHAlt( Graph g, FlagEncoder encoder )
{
super(g, encoder);
}
public Path4CHAlt setSwitchToFrom( boolean b )
{
switchWrapper = b;
return this;
}
#Override
public Path extract()
{
System.out.println("Path4CHAlt extract");
if (edgeEntry == null || edgeTo == null || segmentEdgeEntry == null || segmentEdgeTo == null)
return this;
if (switchWrapper)
{
EdgeEntry ee = edgeEntry;
edgeEntry = edgeTo;
edgeTo = ee;
ee = segmentEdgeEntry;
segmentEdgeEntry = segmentEdgeTo;
segmentEdgeTo = ee;
}
EdgeEntry currEdge = segmentEdgeEntry;
while (EdgeIterator.Edge.isValid(currEdge.edge))
{
processEdge(currEdge.edge, currEdge.adjNode);
currEdge = currEdge.parent;
}
currEdge.parent = edgeEntry;
currEdge = edgeEntry;
while (EdgeIterator.Edge.isValid(currEdge.edge))
{
processEdge(currEdge.edge, currEdge.adjNode);
currEdge = currEdge.parent;
}
setFromNode(currEdge.adjNode);
reverseOrder();
currEdge = segmentEdgeTo;
int tmpEdge = currEdge.edge;
while (EdgeIterator.Edge.isValid(tmpEdge))
{
currEdge = currEdge.parent;
processEdge(tmpEdge, currEdge.adjNode);
tmpEdge = currEdge.edge;
}
currEdge.parent = edgeTo;
currEdge = edgeTo;
tmpEdge = currEdge.edge;
while (EdgeIterator.Edge.isValid(tmpEdge))
{
currEdge = currEdge.parent;
processEdge(tmpEdge, currEdge.adjNode);
tmpEdge = currEdge.edge;
}
setEndNode(currEdge.adjNode);
return setFound(true);
}
}
This is not working all the time. I get exceptions in Path4CH
java.lang.NullPointerException
at com.graphhopper.routing.ch.Path4CH.expandEdge(Path4CH.java:62)
at com.graphhopper.routing.ch.Path4CH.processEdge(Path4CH.java:56)
at com.graphhopper.routing.PathBidirRef.extract(PathBidirRef.java:95)
at com.graphhopper.routing.DijkstraBidirectionRef.extractPath(DijkstraBidirectionRef.java:99)
at com.graphhopper.routing.AbstractBidirAlgo.runAlgo(AbstractBidirAlgo.java:74)
at com.graphhopper.routing.AbstractBidirAlgo.calcPath(AbstractBidirAlgo.java:60)
In Path
java.lang.IllegalStateException: Edge 1506012 was empty when requested with node 1289685, array index:0, edges:318
at com.graphhopper.routing.Path.forEveryEdge(Path.java:253)
at com.graphhopper.routing.Path.calcInstructions(Path.java:349)
I dont know what I am doing wrong. I could really use some help with this.
Thanks.
I solved this issue.
Inside DijkstraBidirectionRef.calcPath I was trying to calculate shortest path from an arbitrary node to source node and vertex node.
The error used to occur because the original call to calcPath was operating on QueryGraph and inside I was creating a new Object of DijkstraBidirectionRef using LevelGraphStorage.
This was a problem because QueryGraph may create virtual nodes and edges for source and target nodes. Call to calcPath(node, virtualNode) operating on LevelGraphStorage would throw an exception.
The fix was to call algo.setGraph(queryGraph) after creating DijkstraBidirectionRef.
I'm currently working with CUSPARSE. I'm having trouble because I don't know how to print a complex number. For example, when I write:
cuComplex a;
a.x=1.2;
a.y=2.2;
How do I print the varable a?
I've tried :
cout<< a;
but it doesn't work.
You will need to overload the << operator to take in cuComplex and cuDoubleComplex data types.
std::ostream& operator<<(std::ostream& strm, const cuComplex& in)
{
char sgn[2] = "+-"
strm << in.x << sgn[in.y < 0] << " i"<< std::abs(in.y);
return strm;
}
You can do the same for cuDoubleComplex
The data in std::complex is identical to the corresponding data in a cuComplex, i.e. you can reinterpret_cast pointers (and therefore arrays, too) of one type to the other – it works in practise and is, I think, actually guaranteed by C++11, you can test it like this:
namespace check_stdComplexdouble_to_cuDoubleComplex_binary_compatibility{
using std::complex;
const complex<double> testarr[] = { complex<double>(0.,.5)
, complex<double>(1.,1.5) };
const cuDoubleComplex* cucomplexd
= reinterpret_cast<const cuDoubleComplex*>(testarr);
auto tester() -> bool {
assert( cuCreal(cucomplexd[0])==0. && cuCimag(cucomplexd[0])==.5
&& cuCreal(cucomplexd[1])==1. && cuCimag(cucomplexd[1])==1.5 );
return true;
}
const bool ok = tester();
bool good(){return ok;}
};
If you call a CUBLAS function that's supposed to read/write from/to an std::complex<float>, you can just give it a reinterpret_casted pointer, e.g.
std::complex<double> result;
xhandle->cublasstat = yhandle->cublasstat
= cublasZdotc( *xhandle->cublashandle
, xhandle->vect_dimension
, xhandle->vector, 1
, yhandle->vector, 1
, reinterpret_cast<cuDoubleComplex*>(&result) );