Duplicate Keys noticed while writing to TOML file; tree.Has() is not working as expected - go

While writing into TOML file using go-toml parser, I'm seeing all duplicate entries.
Which one is correct about tree.WriteTo() function?
a. overwrites the fields in the file
b. appends the tree to the file? i.e., to the existing file, write the tree content again.
I wanted to achieve the update operation to the existing config parameter (present in TOML file).
I tried this:
//Read the config file
tree, _ := toml.LoadFile("/home/robot/test.toml")
//Read user input
reqBody, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
//Check whether the input config parameter is present in the file or not
configArray := strings.Split(string(reqBody), ";")
for index, each := range configArray {
config := strings.Split(each, "=")
fmt.Println("Param name : ", config[0])
fmt.Println("Param value : ", config[1])
fmt.Println(index)
isPresent := tree.Has(config[0])
fmt.Println(isPresent)
if isPresent == true {
tree.Set(config[0], config[1])
}else {
fmt.Println("Config Parameter not found")
}
}
// Now the tree has updated values, update the file.
outputReader, err = os.OpenFile("/home/robot/test.toml",os.O_RDWR,0644)
if err != nil {
fmt.Println("Error opening the file")
}
var numBytes int64
numBytes, err = tree.WriteTo(outputReader)
if err != nil {
fmt.Println("Error writing to the file")
}
fmt.Println(numBytes)
tree.Has() is always returning false, even though the valid key is provided. Not sure why! Please see the output logs pasted.
tree.WriteTo() is appending all the tree entries to the file. i.e., it is not updating the parameter values, but writing everything newly resulting in duplicate configuration parameters in the file.
If tree.WriteTo() is meant to write entire tree content to file, then is there any API or way to update the existing configurations in TOML file?
Output logs:
TOML content (i.e., dump of tree):
Sep 03 13:27:33 mn-0 janus[31157]: [http]
Sep 03 13:27:33 mn-0 janus[31157]: enableAudit = true
Sep 03 13:27:33 mn-0 janus[31157]: idleTimeout = "600s"
Sep 03 13:27:33 mn-0 janus[31157]: logLevel = "debug"
Sep 03 13:27:33 mn-0 janus[31157]: port = 443
Sep 03 13:27:33 mn-0 janus[31157]: readTimeout = "10s"
Sep 03 13:27:33 mn-0 janus[31157]: tlsMode = true
Sep 03 13:27:33 mn-0 janus[31157]: writeTimeout = "10s"
Sep 03 13:27:33 mn-0 janus[31157]: [http.cred]
Sep 03 13:27:33 mn-0 janus[31157]: sessionValidity = "1h"
Sep 03 13:27:33 mn-0 janus[31157]: strictSecureMode = false
Sep 03 13:27:33 mn-0 janus[31157]: users = ["robot"]
Sep 03 13:27:33 mn-0 janus[31157]: [http.ipConfig]
Sep 03 13:27:33 mn-0 janus[31157]: ipAddr = ""
Sep 03 13:27:33 mn-0 janus[31157]: role = "ssh"
Input invalid key:
Sep 03 13:27:33 mn-0 janus[31157]: Param name : http.enableAudt
Sep 03 13:27:33 mn-0 janus[31157]: Param value : true
Sep 03 13:27:33 mn-0 janus[31157]: 0
Sep 03 13:27:33 mn-0 janus[31157]: false
Input valid Key:
Sep 03 13:27:33 mn-0 janus[31157]: Param name : http.enableAudit
Sep 03 13:27:33 mn-0 janus[31157]: Param value : false
Sep 03 13:27:33 mn-0 janus[31157]: 1
Sep 03 13:27:33 mn-0 janus[31157]: false
One more question on unmarshal() or configuration validation while reading,
Say my structure is like this.
type IPConfig struct {
User string
Role string
IPAddr string
}
type MyConfiguration struct {
MyConfiguration MyConfiguration
}
a.
If the TOML file has this:
[ipConfig]
role = "ssh"
ipAddr = ""
i.e., it doesn't have one more parameter, "User". How do I catch this while Unmarshal? At least Unmarshal() will not throw any error here.
b.
If the TOML file has this:
[ipConfig]
role = "ssh"
ipAddr = ""
user = "lauren"
abc = "xyz"
i.e., it has extra configuration parameter "abc". How to catch this? Unmarshal() didn't throw any error even for this.
Any way to get these validation errors?

For question 1:
It is hard to figure out what may be going on without having access to the content of the files. If you believe this is a bug, please open an issue on Github, including the reproduction steps. Thank you!
For question 2:
You need to remove or truncate the file before writing to it.
Go-toml does not know that you are writing to a file. WriteTo takes a io.Writer, which just signifies "something you can write to". So when you open the file for read/write, the "writer" part of the file has a 0 offset. So when toml writes to it (using WriteTo), it will just be replacing bytes to the file.
If you want to overwrite the content of the file using WriteTo, you need to call .truncate(0) or similar on the file before writing to it.
Note: as of writing, comments are discarded during Load. There is an issue on Github asking for that feature.
For question 3:
There is no support for erroring on missing keys or on extra keys. There is an issue open at the moment to support the latter.

Related

Problem providing ExtendedKeyUsage information to CSR during generation in golang

I've stumbled upon a strange problem.
I'm writing a small golang tool, which generates a CSR based on some user-provided input. I'm mostly successful at achieving my goal, but have a problem with ExtendedKeyUsage. Simply put it does not work.
A bit of code with asn1 marshalling of x509 fields:
var oidEmailAddress = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}
var OidExtensionKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 15}
var OidExtensionExtendedKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37}
asn1KeyUsageDigSig, err := asn1.Marshal(asn1.BitString{
Bytes: []byte{byte(x509.KeyUsageDigitalSignature)},
BitLength: 8,
})
asn1KeyUsageDatEnc, err := asn1.Marshal(asn1.BitString{
Bytes: []byte{byte(x509.KeyUsageDataEncipherment)},
BitLength: 8,
})
asn1KeyUsageCAuth, err := asn1.Marshal(asn1.BitString{
Bytes: []byte{byte(x509.ExtKeyUsageClientAuth)},
BitLength: 8,
})
if err != nil {
Error.Fatalf("Can't serialize Extended Key Usage %s", err)
}
Then I create a template and successful at generating and saving a CSR, well almost:
template := x509.CertificateRequest{
RawSubject: asn1Subj,
EmailAddresses: []string{emailAddress},
SignatureAlgorithm: _sigAlg,
ExtraExtensions: []pkix.Extension{
{
Id: OidExtensionExtendedKeyUsage,
Value: asn1KeyUsageCAuth,
},
{
Id: OidExtensionKeyUsage,
Critical: true,
Value: asn1KeyUsageDatEnc,
},
{
Id: OidExtensionKeyUsage,
Critical: true,
Value: asn1KeyUsageDigSig,
},
},
}
csrBytes, _ := x509.CreateCertificateRequest(rand.Reader, &template, privateKey)
And here is an openssl req -in MY_OUTPUT.csr -text -noout
******
ASN1 OID: prime256v1
NIST CURVE: P-256
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
email:someone#somewhere.com
X509v3 Extended Key Usage:
....
X509v3 Key Usage: critical
Key Agreement
X509v3 Key Usage: critical
Encipher Only
Signature Algorithm: ecdsa-with-SHA256
******
My ExtendedKeyUsage is empty, while it should be ClientAuthentication. What am I doing wrong?
I'm expecting to see:
X509v3 Extended Key Usage: ClientAuthentication
I'm seeing empty field. I tried using different set of bytes from another oid, but still nothing. It is as if ExtendedKeyUsage field doesn't allow anything to be written (while it should)
If it is imported:
go ver: go1.19.3 darwin/amd64
I think the problem is when you print the data. The key/value is actually present in the data.
From the code:
var OidExtensionExtendedKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37}
asn1KeyUsageCAuth, err := asn1.Marshal(asn1.BitString{
Bytes: []byte{byte(x509.ExtKeyUsageClientAuth)},
BitLength: 8,
})
ExtraExtensions: []pkix.Extension{
{
Id: OidExtensionExtendedKeyUsage,
//Critical: true,
Value: asn1KeyUsageCAuth,
//Value: {2, 5, 29, 15},
},
OidExtensionExtendedKeyUsage is ASN.1 OID 2.5.29.37 and will be '55 1D 25' when encoded with a DER encoder
You can encode it online to see what binary it will produce (e.g. https://misc.daniel-marschall.de/asn.1/oid-converter/online.php)
asn1KeyUsageCAuth value is 2 (constant defined in x509.go) and will be '00 02' when encoded as ASN.1 BIT STRING with a DER encoder (first 00 is the number of padding bits (none), 02 is the value 2)
Now take the Base64 value of your Certificate Request and decode it with an ASN.1 DER Decoder (for example: https://asn1.io/asn1playground)
MIIBtzCCAV0CAQAwgZwxCzAJBgNVBAYTAkFVMQ8wDQYDVQQIEwZTeWRuZXkxDzAN
BgNVBAcTBlN5ZG5leTETMBEGA1UEChMKc210aENsaWVudDELMAkGA1UECxMCSVQx
JTAjBgNVBAMTHHNtdGgtQ2xpZW50LVk4cDg1bk1pSVNzMGlIZ0ExIjAgBgkqhkiG
9w0BCQEME3NtdGhjbGllbnRAc210aC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB
BwNCAAR4rIgUOxSyXdaML9F9e2gRjuMUK8Q0jiloTb2kAdmbz1RoCEdsZUUxKQcr
0Vud2aW3VIDph1ar4hkqWkM43hxqoF4wXAYJKoZIhvcNAQkOMU8wTTAeBgNVHREE
FzAVgRNzbXRoY2xpZW50QHNtdGguY29tMAsGA1UdJQQEAwIAAjAOBgNVHQ8BAf8E
BAMCAAgwDgYDVR0PAQH/BAQDAgABMAoGCCqGSM49BAMCA0gAMEUCIQDTBj+0Atjy
F1GY8AM2Mv7/X3tsEbmMVdszKw8l6rVsEQIgMiH8CO9nkP0aXdMgp9x4kVjJZK9X
rW3ROydT89D73OA=
Try the full power of OSS' ASN-1Step by downloading a free trial
OSS Nokalva TLV Print Utility Version 8.6.1
Copyright (C) 1997-2022 OSS Nokalva, Inc. All rights reserved.
30 8201B7(439)
30 82015D(349)
02 01 00
30 819C(156)
31 0B
30 09
06 03 550406
13 02 4155
31 0F
30 0D
06 03 550408
13 06 5379646E6579
31 0F
30 0D
06 03 550407
13 06 5379646E6579
31 13
30 11
06 03 55040A
13 0A 736D7468436C69656E74
31 0B
30 09
06 03 55040B
13 02 4954
31 25
30 23
06 03 550403
13 1C 736D74682D436C69656E742D59387038356E4D694953733069486741
31 22
30 20
06 09 2A864886F70D010901
0C 13 736D7468636C69656E7440736D74682E636F6D
30 59
30 13
06 07 2A8648CE3D0201
06 08 2A8648CE3D030107
03 42 000478AC88143B14B25DD68C2FD17D7B68118EE3142BC4348E29684DBDA401D9...
A0 5E
30 5C
06 09 2A864886F70D01090E
31 4F
30 4D
30 1E
06 03 551D11
04 17 30158113736D7468636C69656E7440736D74682E636F6D
30 0B -- HERE IT IS!
06 03 551D25
04 04 03020002
30 0E
06 03 551D0F
01 01 FF
04 04 03020008
30 0E
06 03 551D0F
01 01 FF
04 04 03020001
30 0A
06 08 2A8648CE3D040302
03 48 003045022100D3063FB402D8F2175198F0033632FEFF5F7B6C11B98C55DB332B0F25...
Results
To get more details, please provide/compile a schema for your data.
Scroll down the output above until you find HERE IT IS!
Your key/value is:
30 0B -- a SEQUENCE of 11 bytes
06 03 551D25 -- an item of 3 bytes (551D25 ... OidExtensionExtendedKeyUsage)
04 04 03020002 -- an item of 4 bytes (03 02 0002 ... an item of 2 bytes 0002 ... asn1KeyUsageCAuth)
I would have loved to decode the CSR againt the ASN.1 specification ... but I could not find it :(

golang convert date string(Oct 10 2022) into date format [duplicate]

This question already has answers here:
How to format current time using a yyyyMMddHHmmss format?
(6 answers)
Parsing date/time strings which are not 'standard' formats
(4 answers)
Closed 4 months ago.
I have a date string Oct 10 2022 and I want to convert this to a time object. I have tried with time.Parse, but it always returns 0001-01-01 00:00:00 +0000 UTC
date := "Oct 10 2022"
output, _ := time.Parse(time.ANSIC, date)
fmt.Println(output)
How do I get a time object from the above string?
for cast your favorite time string to time.ANSIC, you must do it like below
date = "Mon Oct 10 15:04:05 2022"
output, _ := time.Parse(time.ANSIC, date)
fmt.Println(output)
other time package constants for cast like below:
Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
ANSIC = "Mon Jan 2 15:04:05 2006"
UnixDate = "Mon Jan 2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
Stamp = "Jan 2 15:04:05"
StampMilli = "Jan 2 15:04:05.000"
StampMicro = "Jan 2 15:04:05.000000"
StampNano = "Jan 2 15:04:05.000000000"

What capabilities required for ioctl() on emmc on systemd?

I want to run my program with systemd with a regular user ( non-root). This program uses ioctl() syscall to access emmc registers.I want to learn which capabilities required to be added to my systemd unit file.
I tried with below unit file:
[Unit]
Description=EMMC-LIFETIME UTILITY
[Service]
User=tron
Group=disk
ExecStart=/HARICI/emmc-lifetime /dev/mmcblk0 -v
CapabilityBoundingSet=CAP_SYS_ADMIN
DeviceAllow=/dev/mmcblk0 rw
[Install]
WantedBy=multi-user.target
Here is the code of emmc-lifetime:
int main(int argc, char **argv)
{
if(argc < 2){
printf("Usage: %s <mmcfilename> (-v)\n", argv[0]);
printf("Example: %s /dev/mmcblk1 -v\n", argv[0]);
return 1;
}
char ext_csd[512], ext_csd_rev;
int fd, ret;
fd = open(argv[1], O_RDWR);
if (fd < 0) {
printf("Failed to open eMMC device, please check which path you have passed\n");
return 1;
}
struct mmc_ioc_cmd idata;
memset(&idata, 0, sizeof(idata));
memset(ext_csd, 0, sizeof(char) * 512);
idata.write_flag = 0;
idata.opcode = MMC_SEND_EXT_CSD;
idata.arg = 0;
idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
idata.blksz = 512;
idata.blocks = 1;
mmc_ioc_cmd_set_data(idata, ext_csd);
ret = ioctl(fd, MMC_IOC_CMD, &idata);
if (ret){
printf("ioctl failed, are you sure it is an MMC device???\n");
return ret;
}
ext_csd_rev = ext_csd[EXT_CSD_REV];
if (ext_csd_rev >= 7) {
if(argc==3 && !strcmp(argv[2],"-v")){
printf("EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A: 0x%02x\n",
ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]);
printf("EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B: 0x%02x\n",
ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]);
printf("EXT_CSD_PRE_EOL_INFO: 0x%02x\n",
ext_csd[EXT_CSD_PRE_EOL_INFO]);
}else{
printf("%d\n",ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]*10);
}
}
if(fd)
close(fd);
return ret;
If I comment out "User=tron" in my unit file, everything works expectedly:
Nov 03 01:17:03 tron systemd[1]: Started EMMC-LIFETIME UTILITY.
Nov 03 01:17:03 tron emmc-lifetime[28294]: EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A: 0x01
Nov 03 01:17:03 tron emmc-lifetime[28294]: EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B: 0x01
Nov 03 01:17:03 tron emmc-lifetime[28294]: EXT_CSD_PRE_EOL_INFO: 0x01
But if I uncomment "User=tron", here is the result:
Nov 03 00:57:17 tron systemd[1]: Started EMMC-LIFETIME UTILITY.
Nov 03 00:57:17 tron emmc-lifetime[27706]: ioctl failed, are you sure it is an MMC device???
Nov 03 00:57:17 tron systemd[1]: emmc-info.service: Main process exited, code=exited, status=255/n/a
Nov 03 00:57:18 tron systemd[1]: emmc-info.service: Unit entered failed state.
Nov 03 00:57:18 tron systemd[1]: emmc-info.service: Failed with result 'exit-code'.
What capabilities are required in my unit file to run my executable as "tron" user ?
Solved. For the capabilities side, it must have CAP_SYS_RAWIO.
We can use :
setcap cap_sys_rawio=+eip /HARICI/emmc-lifetime
And by this way, we can run "emmc-lifetime" binary with non-root user. Please note that, this user must be in "disk" group to be able to open "/dev/mmcblkX"
But unfortunately, this doesn't work in systemd unit files.
In systemd unit files, if you write:
User=some-non-root-user
CapabilityBoundingSet=SOME_CAPABILITY
Does not work. Thats why my above code allways fails.
I must find another way to run my binary with non-root privileges.

Ardulink 2 unable to receive message from analog Pin1 using Serial.print

I have started ardulink mqtt to listen to analog pin 1 of the arduino uno
as follow running on windows 10 with mosquitto mqtt broker 1.5.8
C:\Java\jdk1.8.0_201\bin\java -jar ardulink-mqtt-2.1.0.jar -a 1 -connection "ardulink://serial-jssc?port=COM3&pingprobe=false" -standalone
However I could not get any response despite subscribe the topics with home/devices/ardulink/A1/value/get ?
I do not see any publishing being log from the ardulink log or mosquitto
From the Arduino serial monitor , I did see all the output from Serial.print indicating the sketch was in fact fully uploaded to the Arduino uno.
arduino code
int sensorValue;
// variable to calibrate low value
int sensorLow = 1023;
// variable to calibrate high value
int sensorHigh = 0;
void setup() {
Serial.begin(115200);
// calibrate for the first five seconds after program runs
while (millis() < 5000) {
// record the maximum sensor value
sensorValue = analogRead(A1);
if (sensorValue > sensorHigh) {
sensorHigh = sensorValue;
}
// record the minimum sensor value
if (sensorValue < sensorLow) {
sensorLow = sensorValue;
}
}
}
void loop() {
//read the input from A1 and store it in a variable
sensorValue = analogRead(A1);
Serial.print(sensorValue);
// wait for a moment
delay(1000);
}
Ardulink Mqtt log
C:\ardulink\lib>C:\Java\jdk1.8.0_162\bin\java -jar ardulink-mqtt-2.1.0.jar -a 1 -d 13 -connection "ardulink://serial-jss
c?port=COM4&pingprobe=false" -clientId ardulink
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/ardulink/lib/slf4j-jdk14-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/ardulink/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.JDK14LoggerFactory]
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Apache Camel 2.17.1 (CamelContext: camel-1) is starting
Apr 01, 2019 2:44:04 PM org.apache.camel.management.ManagedManagementStrategy doStart
INFO: JMX is enabled
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.converter.DefaultTypeConverter doStart
INFO: Loaded 182 type converters
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.DefaultRuntimeEndpointRegistry doStart
INFO: Runtime endpoint registry is in extended mode gathering usage statistics of all incoming and outgoing endpoints (c
ache limit: 1000)
Apr 01, 2019 2:44:14 PM org.ardulink.core.ConnectionBasedLink startListening
INFO: Starting listening on pin ANALOG 1
Apr 01, 2019 2:44:14 PM org.ardulink.core.ConnectionBasedLink startListening
INFO: Starting listening on pin DIGITAL 13
Apr 01, 2019 2:44:14 PM org.apache.camel.impl.DefaultComponent preProcessUri
WARNING: Supplied URI 'mqtt:mqttMain?host=tcp://localhost:1883&subscribeTopicNames=home/devices/ardulink/#&connectAttemp
tsMax=1&reconnectAttemptsMax=0' contains unsafe characters, please check encoding
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartCamel
INFO: AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn
this option off as it may improve performance.
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartCamel
INFO: StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at h
ttp://camel.apache.org/stream-caching.html
Apr 01, 2019 2:44:15 PM org.apache.camel.processor.aggregate.AggregateProcessor doStart
INFO: Defaulting to MemoryAggregationRepository
Apr 01, 2019 2:44:15 PM org.apache.camel.processor.aggregate.AggregateProcessor doStart
INFO: Using CompletionInterval to run every 250 millis.
Apr 01, 2019 2:44:15 PM org.apache.camel.component.mqtt.MQTTEndpoint connect
INFO: Connecting to tcp://localhost:1883 using 10 seconds timeout
Apr 01, 2019 2:44:15 PM org.apache.camel.component.mqtt.MQTTEndpoint$2 onConnected
INFO: MQTT Connection connected to tcp://localhost:1883
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route1 started and consuming from: Endpoint[ardulink://serial-jssc?listenTo=A1%2CD13&pingprobe=false&port=C
OM4]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route2 started and consuming from: Endpoint[direct://endOfAnalogAggregation]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route3 started and consuming from: Endpoint[mqtt:mqttMain?host=tcp://localhost:1883&subscribeTopicNames=hom
e/devices/ardulink/#&connectAttemptsMax=1&reconnectAttemptsMax=0]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Total 3 routes, of which 3 are started.
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Apache Camel 2.17.1 (CamelContext: camel-1) started in 10.898 seconds
It seems that you did not flash Ardulink sketch to the Arduino but something self-written (which does not send any message via the serial link). After flashing Ardulink sketch and starting java mqtt client again everything should work.
I managed to resolve the issue after including the standard ardulink protocol , below is the revised arduino code .
int sensorValue;
// variable to calibrate low value
int sensorLow = 1023;
// variable to calibrate high value
int sensorHigh = 0;
// LED pin
const int ledPin = 13;
String inputString = ""; // a string to hold incoming data (this is general code you can reuse)
boolean stringComplete = false; // whether the string is complete (this is general code you can reuse)
void setup() {
// Make the LED pin an output and turn it on
Serial.begin(115200);
Serial.print("alp://rply/");
Serial.print("ok?id=0");
Serial.print('\n'); // End of Message
Serial.flush();
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
// calibrate for the first five seconds after program runs
while (millis() < 5000) {
// record the maximum sensor value
sensorValue = analogRead(A1);
if (sensorValue > sensorHigh) {
sensorHigh = sensorValue;
}
// record the minimum sensor value
if (sensorValue < sensorLow) {
sensorLow = sensorValue;
}
}
digitalWrite(ledPin, LOW);
}
void loop() {
//read the input from A1 and store it in a variable
serialEvent();
sensorValue = analogRead(A1);
if (stringComplete==true){
if(inputString.startsWith("alp://")) {
boolean msgRecognized = true;
if (inputString.substring(6,10)=="ared"){
//Serial.println(sensorValue);
digitalWrite(ledPin, HIGH);
}else{
msgRecognized = false;
}
// Prepare reply message if caller supply a message id (this is general code you can reuse)
int idPosition = inputString.indexOf("?id=");
if(idPosition != -1) {
String id = inputString.substring(idPosition + 4);
// print the reply
Serial.print("alp://rply/");
if(msgRecognized) { // this sketch doesn't know other messages in this case command is ko (not ok)
Serial.print("ok?id=");
} else {
Serial.print("ko?id=");
}
Serial.print(id);
Serial.print('\n'); // End of Message
Serial.flush();
}
}
// clear the string:
inputString = "";
stringComplete = false;
}
if (sensorValue>0){
Serial.print("alp://ared/");
Serial.print("1");
Serial.print("/");
Serial.print(sensorValue);
Serial.print('\n'); // End of Message
Serial.flush();
}
delay(1000);
}
void serialEvent() {
while (Serial.available()>0&&!stringComplete==true) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}

What does 20060102150405 mean?

I would like to get current time value. I found this answer which works for me but don't know why format method take 20060102150405 value? Not like yyyyMMdd hhmmss.
Go's time formatting unique and different than what you would do in other languages. Instead of having a conventional format to print the date, Go uses the reference date 20060102150405 which seems meaningless but actually has a reason, as it's 1 2 3 4 5 6 in the Posix date command:
Mon Jan 2 15:04:05 -0700 MST 2006
0 1 2 3 4 5 6
The timezone is 7 but that sits in the middle, so in the end the format resembles 1 2 3 4 5 7 6.
This online converter is handy, if you are transitioning from the strftime format.
Interesting historical reference: https://github.com/golang/go/issues/444
The time package provides handy constants as well:
const (
ANSIC = "Mon Jan _2 15:04:05 2006"
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano = "Jan _2 15:04:05.000000000"
)
You can use them like this:
t := time.Now()
fmt.Println(t.Format(time.ANSIC))
See https://golang.org/pkg/time/#pkg-constants It is the time "01/02 03:04:05PM '06 -0700" Because each component has a different number (1, 2, 3, etc.), it can determine from the numbers what components you want.
20060102150405 is a date and time format 2006/01/02 15:04:05
package main
import (
"fmt"
"time"
)
func main() {
date1 := time.Now().Format("2006/01/02 15:04")
fmt.Println(date1)//2009/11/10 23:00
date2 := time.Now().Format("20060102150405")
fmt.Println(date2)//20091110230000
}
https://play.golang.org/p/kIfNRQ50JP

Resources