001/*
002 *  $URL: svn://fred.webarts.bc.ca/open/trunk/projects/WebARTS/ca/bc/webarts/tools/WeatherStationRestRequester.java $
003 *  $Author: tgutwin $
004 *  $Revision: 1414 $
005 *  $Date: 2020-11-10 23:03:56 -0800 (Tue, 10 Nov 2020) $
006 */
007/*
008 *
009 *  Written by Tom Gutwin - WebARTS Design.
010 *  Copyright (C) 2020 WebARTS Design, Burnaby Canada
011 *  http://www.webarts.ca
012 *
013 *  This program is free software; you can redistribute it and/or modify
014 *  it under the terms of the GNU General Public License as published by
015 *  the Free Software Foundation; version 3 of the License, or
016 *  (at your option) any later version.
017 *
018 *  This program is distributed in the hope that it will be useful,
019 *  but WITHOUT ANY WARRANTY; without_ even the implied warranty of
020 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
021 *  GNU General Public License for more details.
022 *
023 *  You should have received a copy of the GNU General Public License
024 *  along with this program; if not, write to the Free Software
025 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
026 */
027
028package ca.bc.webarts.tools;
029
030import java.io.IOException;
031import java.io.File;
032import java.io.FileNotFoundException;
033import java.lang.Integer;
034import java.net.HttpURLConnection;
035import java.net.MalformedURLException;
036import java.net.URL;
037import java.net.URLEncoder;
038import java.util.Arrays;
039import java.util.Comparator;
040import java.util.Hashtable;
041import java.util.Set;
042import java.util.Vector;
043
044
045import ca.bc.webarts.tools.RestRequester;
046import ca.bc.webarts.widgets.Util;
047import ca.bc.webarts.widgets.Quick;
048
049import org.apache.commons.codec.binary.Base64;
050
051import nu.xom.Attribute;
052import nu.xom.Builder;
053import nu.xom.Document;
054import nu.xom.Element;
055import nu.xom.Elements;
056import nu.xom.Node;
057import nu.xom.ParsingException;
058import nu.xom.ValidityException;
059import nu.xom.Serializer;
060import nu.xom.XPathException;
061
062import javax.json.*;
063import javax.json.stream.JsonGenerator;
064import javax.json.stream.JsonParser;
065
066
067
068
069/**
070  * This class wraps the communication to the REST interface to Tom's Weather Station.
071  * The web service root URL is http://weatherstation.webarts.bc.ca/rest/
072  *
073  *  Written by Tom Gutwin - WebARTS Design.<br />
074  *  Copyright &copy; 2020 WebARTS Design, Burnaby Canada<br />
075  *  <a href="http://www.webarts.ca">http://www.webarts.ca</a>
076  *
077  * @author  Tom B. Gutwin
078  **/
079public class WeatherStationRestRequester extends RestRequester
080{
081  protected static final String CLASSNAME = "ca.bc.webarts.tools.MusicBrainzRestRequester"; //ca.bc.webarts.widgets.Util.getCurrentClassName();
082  public static final String LOG_TAG = "\n"+CLASSNAME; //+"."+ca.bc.webarts.android.Util.getCurrentClassName();
083
084  /** DEFAULT  IP address to use: 10.0.0.80 .**/
085  protected static final String DEFAULT_WEATHERSTATION_IP = "weatherstation.webarts.bc.ca";
086  protected static final String DEFAULT_WEATHERSTATION_REST_URL_PATHSTR = "/rest";
087
088
089  protected static StringBuilder helpMsg_ = new StringBuilder(SYSTEM_LINE_SEPERATOR);
090  protected static boolean debugOut_ = false;
091  protected static boolean doWrites_ = true;
092
093  /** The start path to use in therest URL. Over-ride this if you extend this class. **/
094  protected String restUrlPath_ = DEFAULT_WEATHERSTATION_REST_URL_PATHSTR;
095  Builder xmlBuilder_ = new Builder();
096
097  /**
098    * Default constructor .
099    *
100    **/
101  public WeatherStationRestRequester()
102  {
103    authenticating_=false;
104    setBaseUrl( "http://"+DEFAULT_WEATHERSTATION_IP+restUrlPath_);
105    setAcceptJSON(true);
106  }
107
108
109  /**
110    * Constructor to customize all connection settings. NOT USED.
111    *
112    **/
113  public WeatherStationRestRequester(String server, String user, String pass)
114  {
115    setBaseUrl( "http://"+server+restUrlPath_);
116    authenticating_=true;
117    setUsername(user);
118    setPassword( pass);
119    setAcceptJSON(true);
120  }
121
122
123  /**
124   * Class main commandLine entry method that has a test command and some convienience commands, as well as a pure rest command.
125   **/
126  public static void main(String [] args)
127  {
128    final String methodName = CLASSNAME + ": main()";
129
130    WeatherStationRestRequester instance = new WeatherStationRestRequester();
131
132    /* Simple way af parsing the args */
133    if (args ==null || args.length<1)
134    {
135      System.out.println(getHelpMsgStr());
136        instance.setAcceptJSON(true); // flase means get XML
137        System.out.println("Can Connect? "+(instance.canConnect()?"Yes":"No"));
138    }
139    /* *************************************** */
140    else
141    {
142      if (args[0].equalsIgnoreCase("weather"))
143      {
144        instance.debugOut_=false;
145        System.out.println(prettyJson(instance.getWeather().toString()));
146      }
147      /* *************************************** */
148      else if (args[0].equalsIgnoreCase("temp"))
149      {
150        instance.debugOut_=false;
151        System.out.println("Temperature = "+instance.getTemperature()+" "+instance.getTemperatureUnits());
152      }
153      /* *************************************** */
154      else if (args[0].equalsIgnoreCase("Pressure"))
155      {
156        instance.debugOut_=false;
157        System.out.println("Pressure = "+instance.getPressure()+" "+instance.getPressureUnits());
158      }
159      /* *************************************** */
160      else if (args[0].equalsIgnoreCase("humidity"))
161      {
162        instance.debugOut_=false;
163        System.out.println("Humidity = "+instance.getHumidity()+" "+instance.getHumidityUnits());
164      }
165      /* *************************************** */
166      else if (args[0].equalsIgnoreCase("altitude"))
167      {
168        instance.debugOut_=false;
169        System.out.println("Altitude = "+instance.getAltitude()+" "+instance.getAltitudeUnits());
170      }
171      /* *************************************** */
172      else
173      {
174        //Send it directly as a rest request
175        instance.restCMD(args);
176      }
177    }
178  } // main
179
180
181
182  /**
183    * Set Method for class field 'restUrlPath_'.
184    *
185    * @param restUrlPath_ is the value to set this class field to.
186    *
187    **/
188  public  void setRestUrlPath(String restUrlPath)
189  {
190    restUrlPath_ = restUrlPath;
191  }  // setRestUrlPath Method
192
193
194  /**
195    * Get Method for class field 'restUrlPath_'.
196    *
197    * @return String - The value the class field 'restUrlPath_'.
198    *
199    **/
200  public String getRestUrlPath()
201  {
202    return restUrlPath_;
203  }  // getRestUrlPath Method
204
205
206  /** Check connectivity to the WeatherStation URL specified by the class parms.
207    * @return true or false
208    **/
209  public boolean canConnect()
210  {
211    if(debugOut_) System.out.println(LOG_TAG+".canConnect("+getBaseUrl()+")");
212
213    boolean retVal = false;
214    if(isInit())
215    {
216      try
217      {
218        if(debugOut_) System.out.println(LOG_TAG+".init = true");
219        String usrlStr = (getBaseUrl()+"/weather").replace(" " ,"%20");
220         if(debugOut_) System.out.println("Can Connect to: "+usrlStr);
221       URL url = new URL(usrlStr);
222        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
223        conn.setRequestMethod("GET");
224        if(acceptJSON_)
225          conn.setRequestProperty("Accept", "application/json");
226        else
227          conn.setRequestProperty("Accept", "application/xml");
228
229         conn.setRequestProperty("User-Agent", USER_AGENT+" ( tgutwin@webarts.ca )");
230
231        if (authenticating_)
232        {
233          //BASE64Encoder enc = new sun.misc.BASE64Encoder();
234          String userpassword = username_ + ":" + password_;
235          //String encodedAuthorization = android.util.Base64.encodeToString( userpassword.getBytes(), android.util.Base64.DEFAULT );
236          String encodedAuthorization = new String(Base64.encodeBase64( (userpassword.getBytes()) ));
237          conn.setRequestProperty("Authorization", "Basic "+ encodedAuthorization);
238        }
239
240        if (conn.getResponseCode() == 200)
241        {
242           retVal=true;
243        } // valid http response code
244        conn.disconnect();
245      }
246      catch (MalformedURLException e)
247      {
248       e.printStackTrace();
249      }
250      catch (IOException e)
251      {
252         e.printStackTrace();
253      }
254    }
255    return retVal;
256  }
257
258
259  /** returns all the Weather data. **/
260  public StringBuilder getWeather()
261  {
262    return serviceGet("/weather");
263  }
264
265
266  /** Reads and parses out the weather JsonObject from the JSON. **/
267  private JsonObject getJsonWeather(String restRequest)
268  {
269    JsonObject jsonWeather = null;
270    String restResponse = serviceGet("/"+restRequest).toString();
271    JsonReader jsonReader = Json.createReader(new java.io.StringReader(restResponse));
272    JsonObject jsonResponse = jsonReader.readObject();
273    jsonReader.close();
274    //System.out.println("jsonOject =\n"+jsonResponse);
275    jsonWeather = jsonResponse.getJsonObject("weather");
276
277    return jsonWeather;
278  }
279
280
281  /** returns temperature. **/
282  public double getTemperature()
283  {
284    JsonObject jsonWeather = getJsonWeather("temp");
285    JsonObject json = jsonWeather.getJsonObject("temperature");
286    double temp = json.getJsonNumber("value").doubleValue();
287    return temp;
288  }
289
290
291  /** returns temperature Units. **/
292  public String getTemperatureUnits()
293  {
294    JsonObject jsonWeather = getJsonWeather("temp");
295    JsonObject json = jsonWeather.getJsonObject("temperature");
296    String units = json.getString("units");
297    return units;
298  }
299
300
301  /** returns pressure. **/
302  public double getPressure()
303  {
304    JsonObject jsonWeather = getJsonWeather("pressure");
305    JsonObject json = jsonWeather.getJsonObject("pressure");
306    double temp = json.getJsonNumber("value").doubleValue();
307    return temp;
308  }
309
310
311  /** returns pressure Units. **/
312  public String getPressureUnits()
313  {
314    JsonObject jsonWeather = getJsonWeather("pressure");
315    JsonObject json = jsonWeather.getJsonObject("pressure");
316    String units = json.getString("units");
317    return units;
318  }
319
320
321  /** returns humidity. **/
322  public double getHumidity()
323  {
324    JsonObject jsonWeather = getJsonWeather("humidity");
325    JsonObject json = jsonWeather.getJsonObject("humidity");
326    double temp = json.getJsonNumber("value").doubleValue();
327    return temp;
328  }
329
330
331  /** returns humidity Units. **/
332  public String getHumidityUnits()
333  {
334    JsonObject jsonWeather = getJsonWeather("humidity");
335    JsonObject json = jsonWeather.getJsonObject("humidity");
336    String units = json.getString("units");
337    return units;
338  }
339
340
341  /** returns altitude. **/
342  public double getAltitude()
343  {
344    JsonObject jsonWeather = getJsonWeather("altitude");
345    JsonObject json = jsonWeather.getJsonObject("altitude");
346    double temp = json.getJsonNumber("value").doubleValue();
347    return temp;
348  }
349
350
351  /** returns altitude Units. **/
352  public String getAltitudeUnits()
353  {
354    JsonObject jsonWeather = getJsonWeather("altitude");
355    JsonObject json = jsonWeather.getJsonObject("altitude");
356    String units = json.getString("units");
357    return units;
358  }
359
360
361  /** returns BatteryVoltage. **/
362  public double getBatteryVoltage()
363  {
364    JsonObject jsonBatt = null;
365    String restResponse = serviceGet("/batteryVoltage").toString();
366    JsonReader jsonReader = Json.createReader(new java.io.StringReader(restResponse));
367    JsonObject jsonResponse = jsonReader.readObject();
368    jsonReader.close();
369    //System.out.println("jsonOject =\n"+jsonResponse);
370    jsonBatt = jsonResponse.getJsonObject("batteryVoltage");
371    double temp = jsonBatt.getJsonNumber("value").doubleValue();
372    return temp;
373  }
374
375
376  /** returns Battery Voltage Units. **/
377  public String getBatteryVoltageUnits()
378  {
379    JsonObject jsonBatt = null;
380    String restResponse = serviceGet("/batteryVoltage").toString();
381    JsonReader jsonReader = Json.createReader(new java.io.StringReader(restResponse));
382    JsonObject jsonResponse = jsonReader.readObject();
383    jsonReader.close();
384    //System.out.println("jsonOject =\n"+jsonResponse);
385    jsonBatt = jsonResponse.getJsonObject("batteryVoltage");
386    String units = jsonBatt.getString("units");
387    return units;
388  }
389
390
391  /** returns BatteryPercent. **/
392  public double getBatteryPercent()
393  {
394    JsonObject jsonBatt = null;
395    String restResponse = serviceGet("/batteryPercent").toString();
396    JsonReader jsonReader = Json.createReader(new java.io.StringReader(restResponse));
397    JsonObject jsonResponse = jsonReader.readObject();
398    jsonReader.close();
399    //System.out.println("jsonOject =\n"+jsonResponse);
400    jsonBatt = jsonResponse.getJsonObject("batteryPercent");
401    double temp = jsonBatt.getJsonNumber("value").doubleValue();
402    return temp;
403  }
404
405
406  /** returns Battery Percent Units. **/
407  public String getBatteryPercentUnits()
408  {
409    JsonObject jsonBatt = null;
410    String restResponse = serviceGet("/batteryPercent").toString();
411    JsonReader jsonReader = Json.createReader(new java.io.StringReader(restResponse));
412    JsonObject jsonResponse = jsonReader.readObject();
413    jsonReader.close();
414    //System.out.println("jsonOject =\n"+jsonResponse);
415    jsonBatt = jsonResponse.getJsonObject("batteryPercent");
416    String units = jsonBatt.getString("units");
417    return units;
418  }
419
420
421  /**
422   * commandLine command executor method for the default rest Command.
423   * It treats each arg as a part of a single rest command and passes it along to the ISY.
424   * @param args the array of commandLine args that got passed in
425   **/
426  protected void restCMD(String [] args)
427  {
428    final String methodName = CLASSNAME + ": restCMD(String [])";
429    // Parse the command
430    String allcommands = args[0];
431    for (int i=1;i< args.length;i++) allcommands+=" "+args[i];
432    if (debugOut_) System.out.print("Sending WeatherStation Rest Service request: "+allcommands);
433    String passedCommand = (allcommands.startsWith(restUrlPath_+"/")?allcommands.substring(restUrlPath_.length()):allcommands);
434    if(debugOut_) System.out.println(" ("+passedCommand+")");
435    passedCommand = (passedCommand.startsWith("/")?passedCommand:"/"+passedCommand);
436    StringBuilder resp =  serviceGet(passedCommand);
437    if (resp!=null)
438    {
439      System.out.println(responseIndenter(resp).toString());
440      System.out.println();
441    }
442    else
443    {
444      System.out.println("Response Error");
445      System.out.println();
446    }
447
448  }
449
450
451  /**
452   * Template method for future commandLine command executor methods.
453   * @param args the array of commandLine args that got passed in
454   **/
455  protected void templateCMD(String [] args)
456  {
457    final String methodName = CLASSNAME + ": testCMD(String [])";
458
459  }
460
461
462    /** gets the help as a String.
463   * @return the helpMsg in String form
464   **/
465  protected static String getHelpMsgStr() {return getHelpMsg().toString();}
466
467
468  /** Makes the JSON string pretty with indenting. **/
469  public static String prettyJson(String jsonStr)
470  {
471    String retVal = jsonStr;
472    retVal = retVal.replace("[", " [\n");
473    retVal = retVal.replace("]", "  ]" + SYSTEM_LINE_SEPERATOR);
474    retVal = retVal.replace("]\n\"", "  ]\"" + SYSTEM_LINE_SEPERATOR);
475    retVal = retVal.replace("{", "  {" + SYSTEM_LINE_SEPERATOR + "      ");
476    retVal = retVal.replace("}", "}" + SYSTEM_LINE_SEPERATOR);
477    retVal = retVal.replace(",", "," + SYSTEM_LINE_SEPERATOR + "      ");
478    retVal = retVal.replace("}" + SYSTEM_LINE_SEPERATOR + "," + SYSTEM_LINE_SEPERATOR, "    }," + SYSTEM_LINE_SEPERATOR);
479    retVal = retVal.replace("[\n", "  [ ");
480    retVal = retVal.replace("        {", "    {");
481    retVal = retVal.replace("[   {", "[\n   {");
482    retVal = retVal.replace("\n}", "\n    }");
483    return retVal;
484  }
485
486
487
488  /** initializes and gets the helpMsg_
489  class var.
490   * @return the class var helpMsg_
491   **/
492  protected static StringBuilder getHelpMsg()
493  {
494    helpMsg_ = new StringBuilder(SYSTEM_LINE_SEPERATOR);
495    helpMsg_.append("---  WebARTS "+CLASSNAME+" Class  -----------------------------------------------------");
496    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
497    helpMsg_.append("--- + $Revision: 1414 $ $Date: 2020-11-10 23:03:56 -0800 (Tue, 10 Nov 2020) $ ---");
498    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
499    helpMsg_.append("-------------------------------------------------------------------------------");
500    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
501    helpMsg_.append("WebARTS ca.bc.webarts.tools.WeatherStationRestRequester Class");
502    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
503    helpMsg_.append("SYNTAX:");
504    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
505    helpMsg_.append("   java ");
506    helpMsg_.append(CLASSNAME);
507    helpMsg_.append(" command or {restCommand}");
508    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
509    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
510    helpMsg_.append("Available commands:");
511    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
512    helpMsg_.append("    weather");
513    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
514    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
515    helpMsg_.append("    temp");
516     helpMsg_.append(SYSTEM_LINE_SEPERATOR);
517     helpMsg_.append(SYSTEM_LINE_SEPERATOR);
518    helpMsg_.append("  Example: java ca.bc.webarts.WeatherStationRestRequester weather ");
519    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
520    helpMsg_.append("---------------------------------------------------------");
521    helpMsg_.append("----------------------");
522    helpMsg_.append(SYSTEM_LINE_SEPERATOR);
523
524    return helpMsg_;
525  }
526
527}