This XML processor is one part of a larger project, an arduino based solar charge controller. This preliminary sketch was an effort to better understand how data is retrieved, parsed, and visualized. The O_dot class contains the visualization functions. All code has been commented extensively.
//import library
import processing.xml.*;
//Create an Array for each SolarDataXML Attribute
/*
Still looking for a global variable that will move iterate properly
using the idList.size()-1 returned a Nullpoint exception error. so I hardcoded the object instatiation for() loops to 13.
*Additonally I need to create a variable that makes an array of Horizontal values based on the number of entries so that I can display the entries in a line.
**Then I must use use the dist() function to make sure the O_dots don't overlap?
*/
// create the Arraylists to capture the XML data
ArrayList idList;
ArrayList timestampList;
ArrayList batteryVoltageList;
ArrayList batteryVoltageSfList;
ArrayList batterySenseList;
ArrayList solarVoltageList;
ArrayList chargeCurrentList;
ArrayList targetVoltageList;
ArrayList controlModeList;
ArrayList controlStateList;
ArrayList hourmeterList;
ArrayList alarmList;
ArrayList faultList;
ArrayList dutyCycleList;
O_dot[] o_dots = new O_dot[14];
PFont nums;
void setup() {
//load the XML document
XMLElement xml = new XMLElement(this, "http://itp.nyu.edu/solarmonitor/recentdata.xml");
XMLElement[] entries = xml.getChildren(); // returns an index of the XML Child elements
int testcounter=0;
// initialize Arraylists
idList = new ArrayList();
timestampList = new ArrayList();
batteryVoltageList = new ArrayList();
batteryVoltageSfList = new ArrayList();
batterySenseList = new ArrayList();
solarVoltageList = new ArrayList();
chargeCurrentList = new ArrayList();
targetVoltageList = new ArrayList();
controlModeList = new ArrayList();
controlStateList = new ArrayList();
hourmeterList = new ArrayList();
alarmList = new ArrayList();
faultList = new ArrayList();
dutyCycleList = new ArrayList();
// for() loop interates through all of the <entry> elements
for (int i= 0; i < entries.length; i++) {
XMLElement[] attributes = entries[i].getChildren();
/*each time the for() loop iterates it captures contents of the child elements and adds the value to the arraylist.
this is actually moving data from the from the attributes[] array which contains each child element of <entry> and is moving it an arraylist that contains only data
from each child.
*/
idList.add(attributes[0].getContent());
timestampList.add(attributes[1].getContent());
batteryVoltageList.add(attributes[2].getContent());
batteryVoltageSfList.add(attributes[3].getContent());
batterySenseList.add(attributes[4].getContent());
solarVoltageList.add(attributes[5].getContent());
chargeCurrentList.add(attributes[6].getContent());
targetVoltageList.add(attributes[7].getContent());
controlModeList.add(attributes[8].getContent());
controlStateList.add(attributes[9].getContent());
hourmeterList.add(attributes[10].getContent());
alarmList.add(attributes[11].getContent());
faultList.add(attributes[12].getContent());
dutyCycleList.add(attributes[13].getContent());
} // end of entries for loop
//Print out arrays of XML data
println("idlist " + idList);
print(timestampList);
print(batteryVoltageList);
print(batteryVoltageSfList);
print(batterySenseList);
println("Solar Voltage" + solarVoltageList);
print(chargeCurrentList);
print(targetVoltageList);
print(controlModeList);
print(controlStateList);
print(hourmeterList);
print(alarmList);
print(faultList);
print(dutyCycleList);
print(entries.length);
//O_dot[] o_dots = new O_dot[entries.length];
/* So I commented the above statement out since the variable was not availible to the draw() function. I kept getting a nullPointerException which seems to be an issue
that one can encounter when passing around empty lists (among other things). this link http://mindprod.com/jgloss/null.html actually gives a good definition of the error. I think it best to pass
the arraylist.size() as a recast string:
*/
int idlistSize = idList.size()-1;
nums = loadFont("ArialRoundedMTBold-24.vlw");
//draw an o_dot object for each XML arraylist data element, in this case BatteryVoltage List.
for(int i = 0; i < idlistSize; i++) {
o_dots[i] = new O_dot();
size(1000,500);
smooth();
}
}
void draw(){
colorMode(RGB,255);
background(255);
int idlistSize2 = idList.size()-1;
/* the first idlistSize is used in the void setup() and is used to create the instances of the o_dot object. This is the same just in
tialized locally for use.*/
int a=0; // initial location of first record to be displayed. Once we enter the for() loop the values will move across the screen
for ( int i = 0; i <idlistSize2; i++){
String SolarVoltVal = (String) solarVoltageList.get(i);
String yString = (String) batteryVoltageSfList.get(i);
int yCord = int(yString);
o_dots[i].display(20,yCord,a);
if( i == idList.size()-2) /*what's going on here? I cannot get the logic to work unless I short the index by 1 value unlike an array the size() function retur
s the correct length of elements */
{
o_dots[i].fade();
o_dots[i].arcPoint(yCord,a,SolarVoltVal);
String tempXMLstring = (String)solarVoltageList.get(i);
o_dots[i].valueTxt(tempXMLstring ,0,24,yCord,a,16.5);
}
/*confused as to why I am getting an instance of this in each object. the iindex formatting is the same as the fade() method and it
is behaving correctly only displaying on the last member of the arraylist.
*/
/* COMMENTED OUT SO THAT I KNOW HOW TO FORMAT THE VARIOUS PARAMETERS. ACTIVE CODE IS IN O_dotgraph class
void valueTxt(String tempXMLval, float tempLowMapVal, float tempHiMapVal,float tempYcord, int tempA, float tempF){
float XMLvalNotMapped = float(tempXMLval); //convert incoming arguement from a string to a float
float XMLval;
float XMLvalFlipflop;
float f = constrain(tempF,0,360); //the rotation angle fed in
float yCord = tempYcord;
int a = tempA;
float LowMapVal = tempLowMapVal;
float HiMapVal = tempHiMapVal;
//XMLval = map(XMLvalNotMapped,LowMapVal,HiMapVal,0,360); // This would map the value to a radian on an arc.
XMLvalFlipflop = map(f,0,360,LowMapVal,HiMapVal);
*/
a = (a + (width/idlistSize2)%width);
/*the width is divided by the number of lines and then that value is used
space out the lines evenly using modulus
And Hey if you know anything about me you'd know this took a minute to figure out!
*/
}
}
class O_dot {
float x;
float fade;
O_dot(){
x = 50;
fade = 1;
}
void display(int TempRadiusXY,float tempYcord, int tempA){
int radiusXY = TempRadiusXY;
float yCord = tempYcord;
int a = tempA;
colorMode(HSB,360,100,100);
fill(20,x,x*2,x*4);
noStroke();
ellipseMode(RADIUS);
//ellipse(x, y, width, height)
ellipse(a,yCord*20,radiusXY + x/4 ,radiusXY + x/4);
stroke(0);
// line(x1, y1, x2, y2)
fill(0,0,0);
ellipse(a,yCord*20,5,5);// just a little point at the tip of the line for looks
line(a,height-1,a,yCord*20);
}
void fade(){
/*How do I make this return a float? After swtiching void to float, I get an error telling me I must return a float. Clearly that
telling me something I don't know. If I can get this as a float then I can use it's value to make the arcpoint follow the edge of
the o_dot.fade().
*/
x = x + fade;
if ((x > 100) || (x < 50)) {
// the value will osscilate between the two values in the if statement, multiply fade by -1 to subtract.
fade = fade * -1;
}
}
void arcPoint(float tempYcord, int tempA,String tempf){
float yCord = tempYcord;
int a = tempA;
pushMatrix();// save original matrix
translate(a,yCord*20);
float tempfConverted = float(tempf);
float f = map( tempfConverted,0,24,0,TWO_PI); // third arguement mapped to "24" as in volts
rotate(f); // when this came AFTER the ellipse was drawn it didn't work because the popMatrix negated it's input.
ellipseMode(RADIUS);
noStroke();
colorMode(RGB,255);
fill(128,128,128);
ellipse(20,-20,5,5);
stroke(1);
//line(20,-20,30,tempYcord *15);
popMatrix();
}
void valueTxt(String tempXMLval, float tempLowMapVal, float tempHiMapVal,float tempYcord, int tempA, float tempF){
float XMLvalNotMapped = float(tempXMLval); //convert incoming arguement from a string to a float
float XMLval;
float XMLvalFlipflop;
float f = constrain(tempF,0,360); //the rotation angle fed in
float yCord = tempYcord;
int a = tempA;
float LowMapVal = tempLowMapVal;
float HiMapVal = tempHiMapVal;
//XMLval = map(XMLvalNotMapped,LowMapVal,HiMapVal,0,360); // This would map the value to a radian on an arc.
XMLvalFlipflop = map(f,0,360,LowMapVal,HiMapVal);
String blah = str(XMLvalNotMapped);
textFont(nums,24);
fill(0);
text(blah,a-20,yCord*15);
}
}