curl --request POST --data?

#include <Process.h>
#include <DHT.h>

#define APIKEY      "XXXXXX" // API KEY
#define DEVICEID    XXX // DEICED id
#define RELAY       XXX //  SENSOR id
#define PICTURE     XXX
#define TEMPERATURE XXX
#define HUMIDITY    XXX

volatile boolean interruptsOccur;

unsigned long lastConnectionTime = 0;
const unsigned long postingInterval = 30 * 1000;

String path = "/mnt/sda1/";

byte relayPin = 2;
byte dht11Pin = 4;

DHT dht;

void setup() {
  // put your setup code here, to run once:
  Bridge.begin();
  dht.setup(dht11Pin);
  pinMode(relayPin, OUTPUT);
  attachInterrupt(0, pinRising, RISING);
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(dht.getMinimumSamplingPeriod());

  float humidity = dht.getHumidity();
  float temperature = dht.getTemperature();

  if (millis() - lastConnectionTime > postingInterval) {
    relayControl();
    if (String(dht.getStatusString()).equals(String("OK"))) {
      postValue(TEMPERATURE, temperature);
      postValue(HUMIDITY, humidity);
    }
  }

  if (interruptsOccur) {
    postPicture();
    interruptsOccur = false;
  }
}

void postValue(int sensor, float value) {
  Process p;

  p.runShellCommand("curl --request POST --data '{\"timestamp\":\"'"
                    + String("`date '+%Y-%m-%dT%T'`")
                    + "'\",\"value\":"
                    + value
                    + "}' --header \"U-ApiKey: XXXXXX\""
                    + " http://api.yeelink.net/v1.0/device/"
                    + DEVICEID
                    + "/sensor/"
                    + sensor
                    + "/datapoints");
}

void postPicture() {
  Process p;
  
  String filename = "";

  p.runShellCommand("date +%s.png");
  while (p.available())
    filename += char(p.read());
  filename.trim();

  p.runShellCommand("fswebcam " + path + filename);
  
  p.runShellCommand("curl --request POST --data-binary @"
                 + path
                 + filename
                 + " --header \"U-ApiKey: XXXXXX\""
                 + " http://api.yeelink.net/v1.1/device/"
                 + DEVICEID
                 + "/sensor/"
                 + PICTURE
                 + "/photos");
}

void relayControl() {
  Process p;
  String returnValue = "";
  p.runShellCommand("curl --request GET --header \"U-ApiKey: "
                    + String(APIKEY)
                    + "\" http://api.yeelink.net/v1.1/device/"
                    + DEVICEID
                    + "/sensor/"
                    + RELAY
                    + "/datapoint/");

  while (p.available() > 0) {
    returnValue += char(p.read());
  }

  if (returnValue.charAt(returnValue.length() - 2) == '1') {
    digitalWrite(relayPin, HIGH);
  }
  else if (returnValue.charAt(returnValue.length() - 2) == '0') {
    digitalWrite(relayPin, LOW);
  }
  
  lastConnectionTime = millis();
}

void pinRising() {
  interruptsOccur = true;
}

dht11- getHumidity, getTemperature data not upload to yeelink
How to modify this code ?

void postValue(int sensor, float value) {
  Process p;

  p.runShellCommand("curl --request POST --data '{\"timestamp\":\"'"
                    + String("`date '+%Y-%m-%dT%T'`")
                    + "'\",\"value\":"
                    + value
                    + "}' --header \"U-ApiKey: XXXXXX\""
                    + " http://api.yeelink.net/v1.0/device/"
                    + DEVICEID
                    + "/sensor/"
                    + sensor
                    + "/datapoints");
}

I have two suggestions:

  1. after calling p.runShellCommand() in postValue, get and display any error message output from the process. It's hard to debug a problem if you don't see the error messages. For example, you could do something line this:
 while (p.available())
    Serial.print((char)p.read());
  1. consider simplifying the sketch, and doing the command formatting (including getting the date) in Python. If you write a Python script that takes two parameters, the sensor ID and value, you can easily test it from the SSH command line. That way, you will be able to try various data values, and directly see any error messages. Then, when you know that is working, you can easily call it with something like:
  p.begin("/usr/bin/python");
  p.addParameter(sensor);
  p.addParameter(value);
  p.run()

Actually, if I were writing this, I'd be doing as much as possible in Python. For example, all of those commands in postPicture() are easier to do in a script on the Linux side, and you just call the single script to run it. I would consider putting all of this in a single script, where the first parameter gives the operation (post value, picture, or relay control) and additional parameters vary depending on operation: sensor/value for post value, and nothing for post picture and relay control. That way, all of the remote system details and keys are down in the one Python file. When I write a system like this, I like to keep the sketch as simple as possible - make it a dumb I/O processor. I find it much easier to update and debug a script on the Linux side, and the Linux side is faster and more powerful, so I do as much of the work as possible on that processor.

ShapeShifter:
I have two suggestions:

  1. after calling p.runShellCommand() in postValue, get and display any error message output from the process. It's hard to debug a problem if you don't see the error messages. For example, you could do something line this:
 while (p.available())

Serial.print((char)p.read());




2) consider simplifying the sketch, and doing the command formatting (including getting the date) in Python. If you write a Python script that takes two parameters, the sensor ID and value, you can easily test it from the SSH command line. That way, you will be able to try various data values, and directly see any error messages. Then, when you know that is working, you can easily call it with something like:



p.begin("/usr/bin/python");
 p.addParameter(sensor);
 p.addParameter(value);
 p.run()





Actually, if I were writing this, I'd be doing as much as possible in Python. For example, all of those commands in postPicture() are easier to do in a script on the Linux side, and you just call the single script to run it. I would consider putting all of this in a single script, where the first parameter gives the operation (post value, picture, or relay control) and additional parameters vary depending on operation: sensor/value for post value, and nothing for post picture and relay control. That way, all of the remote system details and keys are down in the one Python file. When I write a system like this, I like to keep the sketch as simple as possible - make it a dumb I/O processor. I find it much easier to update and debug a script on the Linux side, and the Linux side is faster and more powerful, so I do as much of the work as possible on that processor.

This code print :
No access permission to this sensor.No access permission to this sensor.No access permission to this sensor.No access permission to this sensor.No access permission to this sensor.

 void postValue(int sensor, float value) {
  Process p;
 
  

  p.runShellCommand("curl --request POST -d '{\"timestamp\":\"'"
                    + String("`date '+%Y-%m-%dT%T'`")
                    + "'\",\"value\":"
                    + value
                    + "}' --header \"U-ApiKey: XXXXXX\""
                    + " http://api.yeelink.net/v1.0/device/"
                    + DEVICEID
                    + "/sensor/"
                    + sensor
                    + "/datapoints");

  while (p.available())
    Serial.print((char)p.read());

}

sensor is DHT11.

a2961656123:
sensor is DHT11.

That doesn't matter. It's not a problem with your sketch seeing the sensor. The error message is coming from yeelink - it would appear that it doesn't understand your sensor ID value. Or the value is valid, but the permissions for the sensor are not set up properly with yeelink, and it won't allow writing to it. Or perhaps there is something malformed in your request format that it doesn't understand. This is a yeelink problem - I tried to look at their documentation to see if I could see any clues, but the site is in a language I don't speak.

Have you tried manually posting data to yeelink? That is always the first step to make sure the service is set up properly, and that you understand the syntax and mechanisms of making a request. I use Poster with Forefox for such work: https://addons.mozilla.org/en-US/firefox/addon/poster/

Until you are sure you understand the posting syntax, and you know the service will accept data manually, there is no point in trying to write code to make the request. With Poster you can quickly and easily work out the details of the proper syntax and settings, without having to spend a lot of time writing and debugging code.

Once you can reliably send data with Poster, make note of the final syntax details that you have determined, and then try to write code that duplicates that. At that point, you're just making sure you are getting the string formatting right, and not trying to work out yeelink issues at the same time.

ShapeShifter:
That doesn't matter. It's not a problem with your sketch seeing the sensor. The error message is coming from yeelink - it would appear that it doesn't understand your sensor ID value. Or the value is valid, but the permissions for the sensor are not set up properly with yeelink, and it won't allow writing to it. Or perhaps there is something malformed in your request format that it doesn't understand. This is a yeelink problem - I tried to look at their documentation to see if I could see any clues, but the site is in a language I don't speak.

yeelink API documentation : http://www.yeelink.net/developer/apidoc/11
Ex: CURL
curl --request POST --data-binary @datafile.txt
--header "U-ApiKey: YOUR_API_KEY_HERE" http://api.yeelink.net/v1.0/device/12/sensor/3/datapoints

In several places in the translation of that page, it mentions:

the need to increase the API Key in HTTP Header to authorize the writing operation, please refer to the specific API Key.

Did you do that? From the "No access permission to this sensor" error message you are getting, it seems like you might not have enabled write access?

ShapeShifter:
In several places in the translation of that page, it mentions:

Did you do that? From the "No access permission to this sensor" error message you are getting, it seems like you might not have enabled write access?

  p.runShellCommand("curl --request POST -data '{\"timestamp\":\"'"
                    + String("`date '+%Y-%m-%dT%T'`")
                    + "'\",\"value\":"
                    + value
                    + "}' --header \"U-ApiKey: XXXXX\""
                    + " http://api.yeelink.net/v1.0/device/"
                    + DEVICEID
                    + "/sensor/"
                    + sensor
                    + "/datapoints");

   while (p.available())
   Serial.print((char)p.read());

}

print :
--curl--"timestamp":"2016-08-01T09:58:10"
--curl--"value":31.00
No access permission to this sensor.--curl--"timestamp":"2016-08-01T09:58:11"
--curl--"value":34.00
No access permission to this sensor.--curl--"timestamp":"2016-08-01T09:58:26"
--curl--"value":31.00
No access permission to this sensor.--curl--"timestamp":"2016-08-01T09:58:26"
--curl--"value":34.00
No access permission to this sensor.--curl--"timestamp":"2016-08-01T09:58:41"
--curl--"value":31.00
No access permission to this sensor.--curl--"timestamp":"2016-08-01T09:58:42"
--curl--"value":34.00

Can U test it? I give you API ID
#define APIKEY "07b0df386a8650ea66fb0181628c212d"
#define DEVICEID 349960
#define RELAY 392350
#define PICTURE 392351
#define TEMPERATURE 392392
#define HUMIDITY 392393

This is Data page :
http://www.yeelink.net/devices/349960/#sensor_392392
http://www.yeelink.net/devices/349960/#sensor_392393

ShapeShifter:
In several places in the translation of that page, it mentions:

Did you do that? From the "No access permission to this sensor" error message you are getting, it seems like you might not have enabled write access?

Hello ShapeShifter, I`m solved。
code is

#define TEMPERATURE "XXX"
#define HUMIDITY    "XXX"


void postValue(String sensor, float value) {
  Process p;

add "" and String data can upload to yeelink.
and~thank you very much ShapeShifter,
while (p.available()) Serial.print((char)p.read());
this code let me found the erorr, “int sensor” → “String sensor” is ok~