I use this for logging from inside a rule, using an HTTP GET, for saving data from Maker API to disk on a Windows host.
I will probably add emailing to this app soon so I can send the files as attachments to IFTTT and have them save the attachment to Google drive, I imagine.
Here is the rule
C# Code Here
Heres the Project Blog
And the possibility of using the maker API to run real-time graphs and gauges like in Node-Red.
I'm working on a wee project building an ERV system using my Hubitat, Arduino and Xiaomi.
Usage
HTTP call in rule machine
You can see how the above URL works ?csv=name of device 1, name of device 2
?csv=name of device 1, name of device 2
Makes the logger log a file on the Windows host for the whole day, and return all the rows currently in the file.
?json=name of device 1, name of device 2
Makes a log for the yyyy-MM-dd-hh-mm-ss
The file name is logNAME-yyyy-MM-dd.txtx for CSV data and logNAME-yyyy-MM-dd-hh-mm-ss.json for the JSON format.
As long as the call begins with log and has the .svs extension it will work.
if you use http://192.168.1.71:82/logtempertures.svs?json=Outside%20Climate, for example, you get back JSON
The JSON with the current device value and is stored here, a new file for every second.
You need to set the Get All Devices URL e.g. http://192.168.1.65/apps/api/6/devices?access_token=???????????????????? to point to your Hub in App.Config
A JavaScript usage example
$.getJSON('http://192.168.1.71:82/logtempertures.svs?json=Outside%20Climate', function(json){
console.log(json[0].attributes)
var val = json[0].attributes[6].currentValue;
console.log(json[0].val)
});
The zip file has a few JavaScipt examples
The C# that does the work
static void HTTPserver_SVSrequest(object o, HTTPrequest Request)
{
if (Request.Action != null)
Console.WriteLine("Action: " + Request.Action.Trim());
if (Request.Args != null)
Console.WriteLine("Post Args: " + Request.Args);
if (Request.Action.Trim().ToLower().EndsWith(".svs"))
{
if (Request.Action.ToLower().StartsWith("log"))
{
JArray deviceJSON = new JArray();
//Request.RawURL
//"/LogClimate.svs?ids=Hallway%20Climate,Outside%20Climate"
string args = "";
if (Request.Method.Trim() == "POST")
args = Request.Args.TrimEnd('#').Replace("%20", " ");
else if (Request.Method.Trim() == "GET")
args = Request.RawURL.Replace("%20", " ");
string[] dlabs = args.Split('=')[1].Split(',');
using (WebClient wc = new WebClient())
{
string url = Settings.Default.GetAllDevicesURL;
string sjson = wc.DownloadString(url);
DeviceList = JArray.Parse(sjson);
}
string CSVline = DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss") + ",";
//Each ID
foreach (string dlab in dlabs)
{
//Find Device
foreach (JObject jo in DeviceList)
{
/*
{
"id":"673",
"name":"Xiaomi Temperature Humidity Sensor",
"label":"Hallway Climate"
},
*/
if (jo["label"].ToString() == dlab)
{
string did = jo["id"].ToString();
CSVline += ("device," + dlab + ",ld," + did + ",");
using (WebClient wc = new WebClient())
{
//e.g. http://192.168.1.65/apps/api/6/devices/673?access_token=ae6f8845-6916-4b8a-a9b2-67f7f5261ef7
string url = string.Format("http://192.168.1.65/apps/api/6/devices/{0}?access_token=ae6f8845-6916-4b8a-a9b2-67f7f5261ef7", did);
string sjson = wc.DownloadString(url);
JObject jod = JObject.Parse(sjson);
deviceJSON.Add(jod);
/*
"attributes":[
{
"name":"battery",
"currentValue":70,
"dataType":"NUMBER"
},
{
"name":"batteryLastReplaced",
"currentValue":"Jul 20 2020",
"dataType":"STRING"
},
{
"name":"humidity",
"currentValue":31.9,
"dataType":"NUMBER"
},
{
"name":"lastCheckinEpoch",
"currentValue":"1601591927215",
"dataType":"STRING"
},
{
"name":"lastCheckinTime",
"currentValue":"Oct 2, 2020 11:38:47 AM",
"dataType":"DATE"
},
{
"name":"pressure",
"currentValue":null,
"dataType":"NUMBER"
},
{
"name":"temperature",
"currentValue":23.79,
"dataType":"NUMBER"
}
],
*/
string rejectAttr = "lastCheckinTime,lastCheckinEpoch,batteryLastReplaced";
JArray attrs = JArray.Parse(jod["attributes"].ToString());
foreach(JObject attr in attrs)
if(!rejectAttr.Contains(attr["name"].ToString()) )
CSVline += (attr["name"].ToString() + "," + attr["currentValue"].ToString() + ",");
}//End of using (WebClient wc = new WebClient())
break;//Whole device done
}//End of if (jo["label"].ToString() == dlab)
}//End of foreach (JObject jo in DeviceList)
}//End of foreach (string dlab in dlabs)
CSVline = CSVline.TrimEnd(',');
//WRITE AS JSON
if (args.Contains("json"))
{
string folder = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\json\";
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
string file = folder + Request.Action.Replace("/", "\\") + "-" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss") + ".json";
string sjson = JsonConvert.SerializeObject(deviceJSON);
File.WriteAllText(file, sjson);
//Send back last value usefull
HTTPserver.Response(sjson);
}
//WRITE AS CSV TEXT
else if (args.Contains("csv"))
{
string folder = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\data\";
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
string file = folder + Request.Action.Replace("/", "\\") + "-" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
//Add this line
File.AppendAllText(file, CSVline + "\r\n");
//Get whole file so far
string CSVlines = File.ReadAllText(file);
HTTPserver.Response(CSVlines);
}
}//End of if (Request.Action.ToLower().StartsWith("logclimate"))
}//End of else if (Request.Action.Trim().ToLower().EndsWith(".svs"))
}
Hubitat I may be missing something, but if not, when are you going to add some JSON handling into your marvellous product, please?