Ruben Laguna’s blog

Warning: Invalid Keyword ‘DNSCache’ (webalizer.conf) in MacPorts (Mac OS X)

If you installed webalizer via MacPorts in your Mac OS X you must know that it comes without dns support. That’s why you’re getting those

Warning: Invalid keyword 'DNSCache' (webalizer.conf)
Warning: Invalid keyword 'DNSChildren' (webalizer.conf)
Warning: Invalid keyword 'DNSCache' (webalizer.conf)
Warning: Invalid keyword 'DNSChildren' (webalizer.conf)

To enable it , uninstall webalizer

sudo port -d uninstall webalizer

Edit the Portfile for webalizer

vi /opt/local/var/macports/sources/rsync.macports.org/release/ports/www/webalizer/Portfile

to add an

  —enable-dns \

(note the ending backslash “\”) in the configure.args section just before of

 --with-png=${prefix}/lib

now you have to install BerkeleyDB (in case it is not already installed)

sudo port -d install db47

then execute the port clean and port install and you should get a working dns enabled webalizer

sudo port -d clean webalizer
sudo port -d install webalizer

Hope it helps

Listen to Radio Online (in Mac OS X)

I want to listen to Sverige Radio P1 in Mac OS X. It seems that Windows Media Player and RealPlayer are the only supported options so I thought I couldn’t do it but then I found Flip4Mac WMV Player also known as Windows Media® Components for QuickTime, by Flip4Mac™ . After installing it and restarting Safari 4, I could listen to SR P1 with no problem.

References:

How to Fix the Cyberduck Quicksilver Plugin

If the CyberDuck plugin is not working for you, (you can’t right-arrow to see the bookmarks) make sure that you changed the default nicknames of the bookmarks.

Probably if you open the Console you’ll find some “missing nickname” errors there.


[March19] [March 19] 7:31:22 PM Quicksilver[6037] Error: No 'Nickname' key for favorite:

I found the answer in this google group Can’t right-arrow into Cyberduck – Blacktree: Quicksilver | Google Groups .

Arduino Library for Hmc6352

As part of my Xbee sensor project, I created an object oriented API to access HMC6352 compass functionality and I decided to make it downloadable as an Hmc6352 Arduino Library.
Just unzip the file in the $arduino_home/hardware/libraries/. At the end you should end with $arduino_home/hardware/libraries/Hmc6352.

The library includes an example on how to use it (in File ⇒ Sketchbook ⇒ Examples ⇒ Library-Hmc6352 ⇒ Hmc6352.

Hmc6352 example menu

The example looks like this (also available as gist):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<span class='line'>/*
</span><span class='line'> * hmc6352example.pde
</span><span class='line'> * 
</span><span class='line'> * Copyright (c) 2009 Ruben Laguna &lt;ruben.laguna at gmail.com>. All rights reserved.
</span><span class='line'> * 
</span><span class='line'> * 
</span><span class='line'> * This program is free software: you can redistribute it and/or modify
</span><span class='line'> * it under the terms of the GNU General Public License as published by
</span><span class='line'> * the Free Software Foundation, either version 3 of the License, or
</span><span class='line'> * (at your option) any later version.
</span><span class='line'> * 
</span><span class='line'> * This program is distributed in the hope that it will be useful,
</span><span class='line'> * but WITHOUT ANY WARRANTY; without even the implied warranty of
</span><span class='line'> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
</span><span class='line'> * GNU General Public License for more details.
</span><span class='line'> * 
</span><span class='line'> * You should have received a copy of the GNU General Public License
</span><span class='line'> * along with this program.  If not, see &lt;http://www.gnu.org/licenses/>.
</span><span class='line'> */
</span><span class='line'>
</span><span class='line'> 
</span><span class='line'>#include &lt;hmc6352.h>
</span><span class='line'> 
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>//set up hmc6352
</span><span class='line'>Hmc6352 hmc6352;
</span><span class='line'>
</span><span class='line'>  
</span><span class='line'>void setup()  {  
</span><span class='line'>  Serial.begin(9600);
</span><span class='line'>  delay(100);
</span><span class='line'>  
</span><span class='line'>  Serial.print("RST\r\n");delay(100);  
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>void loop() 
</span><span class='line'>{ 
</span><span class='line'>  hmc6352.wake();
</span><span class='line'>  float a = hmc6352.getHeading();
</span><span class='line'>  hmc6352.sleep();
</span><span class='line'> 
</span><span class='line'>  Serial.print((int)a,DEC);
</span><span class='line'>  Serial.print("\r\n");
</span><span class='line'>  
</span><span class='line'>}</span>

References:

DS1620 Temperature Sensor Library for Arduino

I talked about the DS1620 in a previous post. Now I created a DS1620 library for Arduino that has a more object oriented interface. The library has to be unpacked in the $arduino_home/hardware/libraries directory. After unzipping the library you should end up with a $ARDUINO_HOME/hardware/libraries/ds1620 directory.

The library contains an example that can be accessed through the File ⇒ Sketchbook ⇒ Examples ⇒ Library-ds1620 ⇒ ds1620.

library ds1620 example menu

The example looks like this:

/*
 ds1620 example
*/

#define ledPin 13

#include <stdlib.h>
#include <math.h>
//#include <Stdio.h>



#include "ds1620.h"


// set up ds1620
// this sets the pins as outputs
Ds1620 ds1620 = Ds1620(7/*rst*/,8/*clk*/,9/*dq*/);
 
void setup()
{
  
  // configure ds1620
  // this does sets cpu mode 1shot
  // see datasheet http://pdfserv.maxim-ic.com/en/ds/DS1620.pd 
  ds1620.config();

  Serial.begin(9600);
  delay(100);
  
  
  Serial.print("RST\r\n");  
}

void loop() 
{ 
   // start the temperature conversion
   // 1 shot mode
   ds1620.start_conv();
   
   // read the last temperature converson
   int raw_data = ds1620.read_data();
   
   // stop conversion not really needed since we are in 
   // 1 shot mode
   ds1620.stop_conv();
   float temp = raw_data / 2.0; 
   Serial.print((int)temp,DEC);
   Serial.print("\r\n");
}

References.

Arduino XBee Sensor (Temperature, Tilt, Compass, and Ambient Light)

I finally put together an Arduino Pro Mini, the XBee, the MMA7260Q, the HMC6352, the TEMT6000 and the DS1620.

This is how it looks like on the prototyping board (ugly, I know)

xbee sensors on protoboard

Hopefully it would look better when I move it to the PCB. But before doing that I need to get the battery power set up. (I’m waiting for a MAX756 DC-DC voltage regulator and CoilCraft inductors to arrive)

The XBee uses the API mode and I implemented a Zigbee Application Layer protocol stack in Arduino instead of using the Serial interface like the rest of Arduino-XBee project that I’ve seen.

I implemented the Temperature Measurement Cluster ID (0x0402) and the Illuminance Measurement Cluster ID (0x0400) (see Zigbee Cluster Library ). Then I also two non-standard cluster ids, the Tilt Measurement Cluster ID (0xFC00) and the Heading Measurement Cluster ID (0xFC01).

You can download the source code for the Arduino project.

Below you can find the main project file, from here I pass the control to the Xbee library and control the sleep cycle of the Arduino. The XBee library will invoke the callbacks (fgetTemperature, etc) when it needs the data. ie. it receives a read command. The callbacks(function pointers) point to functions in the main file (readDs1620, readTEMT6000, etc) and the callbacks are implemented in this main file which also contains the calls to ds1620 library, hmc6352 library and mma7260q library. To see the source files of the libraries download the sources. I also made independent libraries for ds1620, hmc6352 and mma7260q each one containing an example.

The code (also as gist):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
<span class='line'>/*
</span><span class='line'> XBee sensor
</span><span class='line'> ZCL Temperature Measurement Cluster
</span><span class='line'>*/
</span><span class='line'>
</span><span class='line'>#define ledPin 13
</span><span class='line'>
</span><span class='line'>#define lcdPin 6
</span><span class='line'>#define temt6000Pin 3
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>#include &lt;stdlib.h>
</span><span class='line'>#include &lt;math.h>
</span><span class='line'>
</span><span class='line'>#include &lt;Stdio.h>
</span><span class='line'>#include &lt;SoftwareSerial.h>
</span><span class='line'>#include &lt;avr/power.h>
</span><span class='line'>#include &lt;avr/sleep.h>
</span><span class='line'>#include "XBeeLibrary.h"
</span><span class='line'>#include "ds1620.h"
</span><span class='line'>#include &lt;Wire.h>
</span><span class='line'>#include "hmc6352.h"
</span><span class='line'>#include &lt;math.h>
</span><span class='line'>#include &lt;float.h>
</span><span class='line'>#include &lt;limits.h>
</span><span class='line'> 
</span><span class='line'> 
</span><span class='line'>
</span><span class='line'>int xaxis = 0;
</span><span class='line'>int yaxis = 1;   
</span><span class='line'>int zaxis = 2;   
</span><span class='line'>
</span><span class='line'>float xa=0;
</span><span class='line'>float ya=0;
</span><span class='line'>float za=0;
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>int minx = INT_MAX;
</span><span class='line'>int maxx = 0;
</span><span class='line'>int miny = INT_MAX;
</span><span class='line'>int maxy = 0;
</span><span class='line'>int minz = INT_MAX;
</span><span class='line'>int maxz = 0;
</span><span class='line'>
</span><span class='line'>float g0x = 0;
</span><span class='line'>float g0y = 0;
</span><span class='line'>float g0z = 0;
</span><span class='line'>
</span><span class='line'>//long time1 = 0;
</span><span class='line'>//long time2 = 0;
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>// set up a new serial port
</span><span class='line'>SoftwareSerial lcdSerial = SoftwareSerial(lcdPin,lcdPin);
</span><span class='line'>byte pinState[16];
</span><span class='line'>byte backlightValue = 0x9D;
</span><span class='line'>
</span><span class='line'>// set up ds1620
</span><span class='line'>Ds1620 ds1620 = Ds1620(7/*rst*/,8/*clk*/,9/*dq*/);
</span><span class='line'>
</span><span class='line'>//set up hmc6352
</span><span class='line'>Hmc6352 hmc6352;
</span><span class='line'>
</span><span class='line'>  
</span><span class='line'>void setup()  {  
</span><span class='line'>  pinMode(ledPin, OUTPUT);
</span><span class='line'>  pinMode(lcdPin, OUTPUT);
</span><span class='line'>  pinMode(temt6000Pin,INPUT);
</span><span class='line'>  pinMode(xaxis,INPUT);
</span><span class='line'>  pinMode(yaxis,INPUT);
</span><span class='line'>  pinMode(zaxis,INPUT);  
</span><span class='line'>  
</span><span class='line'>  // set the data rate for the SoftwareSerial port
</span><span class='line'>  lcdSerial.begin(4800);
</span><span class='line'>  
</span><span class='line'>  Serial.begin(9600);
</span><span class='line'>  delay(100);
</span><span class='line'>  
</span><span class='line'>  // configure ds1620
</span><span class='line'>  ds1620.config();
</span><span class='line'>  
</span><span class='line'>  //initial calibration of the MMA7260q 
</span><span class='line'>  minx = 173.0;
</span><span class='line'>  miny = 192.0;  
</span><span class='line'>  minz = 258.0;
</span><span class='line'>  
</span><span class='line'>  maxx = 766.0;  
</span><span class='line'>  maxy = 720.0;  
</span><span class='line'>  maxz = 914.0;
</span><span class='line'>  
</span><span class='line'>  g0x = 469.0;
</span><span class='line'>  g0y = 456.0;
</span><span class='line'>  g0z = 586.0;
</span><span class='line'>  
</span><span class='line'>  lcdPrint("RST\r\n");delay(100);  
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>long start =0;
</span><span class='line'>
</span><span class='line'>void loop() 
</span><span class='line'>{ 
</span><span class='line'>  struct zigbee zb;
</span><span class='line'>  unsigned long time;
</span><span class='line'>  unsigned long time2;
</span><span class='line'>  
</span><span class='line'>  xbee_init(&zb);  
</span><span class='line'>  zb.fgetTemperature = &readDs1620;
</span><span class='line'>  zb.fprogress = &toggleLedPin;
</span><span class='line'>  zb.ferror = &lcdPrint;
</span><span class='line'>  zb.fprint = &lcdPrint;
</span><span class='line'>  zb.fprintHex = &lcdPrintBuffer;
</span><span class='line'>  zb.fgetHeading = &readHmc6352;
</span><span class='line'>  zb.fgetIlluminance = &readTEMT6000;
</span><span class='line'>  zb.fgetTilt = readMMA7260Q;
</span><span class='line'>  
</span><span class='line'>  
</span><span class='line'>  XBee xbee(&zb);  
</span><span class='line'>   
</span><span class='line'>  time = 0;
</span><span class='line'>  time2 = 0;
</span><span class='line'>  
</span><span class='line'>  //lcdPrintInt(millis());
</span><span class='line'>  while(1) 
</span><span class='line'>  {
</span><span class='line'>    xbee.serve();
</span><span class='line'>    if ((millis()-time) > 500) {
</span><span class='line'>      time = millis();
</span><span class='line'>      toggle(ledPin);
</span><span class='line'>      //lcdSerial.print("ab\r\n");
</span><span class='line'>    }
</span><span class='line'>    
</span><span class='line'>    
</span><span class='line'>    
</span><span class='line'>    int pfx /*valx*/ = analogRead(xaxis);    // read the value from the sensor
</span><span class='line'>    int pfy /*valy*/ = analogRead(yaxis);    // read the value from the sensor
</span><span class='line'>    int pfz /*valz*/ = analogRead(zaxis);    // read the value from the sensor
</span><span class='line'>  
</span><span class='line'>  
</span><span class='line'>    autoZeroCalibration(pfx,pfy,pfz);
</span><span class='line'>  
</span><span class='line'>    
</span><span class='line'>    
</span><span class='line'>    if ((millis()-time2) > 25000) {
</span><span class='line'>      goToSleep();
</span><span class='line'>      time2 = millis();
</span><span class='line'>    }
</span><span class='line'>    
</span><span class='line'>  }  
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>void goToSleep()
</span><span class='line'>{
</span><span class='line'>    /* Now is the time to set the sleep mode. In the Atmega8 datasheet
</span><span class='line'>     * http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
</span><span class='line'>     * there is a list of sleep modes which explains which clocks and 
</span><span class='line'>     * wake up sources are available in which sleep modus.
</span><span class='line'>     *
</span><span class='line'>     * In the avr/sleep.h file, the call names of these sleep modus are to be found:
</span><span class='line'>     *
</span><span class='line'>     * The 5 different modes are:
</span><span class='line'>     *     SLEEP_MODE_IDLE         -the least power savings 
</span><span class='line'>     *     SLEEP_MODE_ADC
</span><span class='line'>     *     SLEEP_MODE_PWR_SAVE
</span><span class='line'>     *     SLEEP_MODE_STANDBY
</span><span class='line'>     *     SLEEP_MODE_PWR_DOWN     -the most power savings
</span><span class='line'>     * 
</span><span class='line'>     */  
</span><span class='line'>     
</span><span class='line'>  set_sleep_mode(SLEEP_MODE_IDLE);   // sleep mode is set here
</span><span class='line'>
</span><span class='line'>  sleep_enable();          // enables the sleep bit in the mcucr register
</span><span class='line'>                             // so sleep is possible. just a safety pin 
</span><span class='line'>  
</span><span class='line'>  power_adc_disable();
</span><span class='line'>  power_spi_disable();
</span><span class='line'>  power_timer0_disable();
</span><span class='line'>  power_timer1_disable();
</span><span class='line'>  power_timer2_disable();
</span><span class='line'>  power_twi_disable();
</span><span class='line'>  
</span><span class='line'>  digitalWrite(ledPin, 0);
</span><span class='line'>  lcdPrint("slp\r\n");
</span><span class='line'>  
</span><span class='line'>  sleep_mode();            // here the device is actually put to sleep!!
</span><span class='line'> 
</span><span class='line'>  digitalWrite(ledPin, 1);
</span><span class='line'> lcdPrint("wk\r\n");
</span><span class='line'>  
</span><span class='line'>                              // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
</span><span class='line'>  sleep_disable();         // first thing after waking from sleep:
</span><span class='line'>                            // disable sleep...
</span><span class='line'>
</span><span class='line'>  power_all_enable();
</span><span class='line'>   
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>void toggleLedPin() {
</span><span class='line'>  toggle(ledPin);
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>float readDs1620()
</span><span class='line'>{
</span><span class='line'>  ds1620.start_conv();
</span><span class='line'>  int raw_data = ds1620.read_data();
</span><span class='line'>  ds1620.stop_conv();
</span><span class='line'>  float temp = raw_data / 2.0; 
</span><span class='line'>  return temp;
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>float readHmc6352()
</span><span class='line'>{
</span><span class='line'>  hmc6352.wake();
</span><span class='line'>  float a = hmc6352.getHeading();
</span><span class='line'>  hmc6352.sleep();
</span><span class='line'> 
</span><span class='line'>  return a;
</span><span class='line'> 
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>void toggle(int pinNum) {
</span><span class='line'>  // set the LED pin using the pinState variable:
</span><span class='line'>  digitalWrite(pinNum, pinState[pinNum]); 
</span><span class='line'>  // if pinState = 0, set it to 1, and vice versa:
</span><span class='line'>  pinState[pinNum] = !pinState[pinNum];
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>int readTEMT6000()
</span><span class='line'>{
</span><span class='line'>  int val = analogRead(temt6000Pin);   
</span><span class='line'>  return val;
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>float readMMA7260Q(int a)
</span><span class='line'>{
</span><span class='line'>    int pfx /*valx*/ = analogRead(xaxis);    // read the value from the sensor
</span><span class='line'>    int pfy /*valy*/ = analogRead(yaxis);    // read the value from the sensor
</span><span class='line'>    int pfz /*valz*/ = analogRead(zaxis);    // read the value from the sensor
</span><span class='line'>
</span><span class='line'>    autoZeroCalibration(pfx,pfy,pfz);
</span><span class='line'>  
</span><span class='line'>    int fx = (pfx - g0x);
</span><span class='line'>    int fy = (pfy - g0y);
</span><span class='line'>    int fz = (pfz - g0z);
</span><span class='line'>    
</span><span class='line'>    float ax = (fx*2.0)/((maxx-minx));    
</span><span class='line'>    float ay = (fy*2.0)/((maxy-miny));
</span><span class='line'>    float az = (fz*2.0)/((maxz-minz));
</span><span class='line'>    
</span><span class='line'> 
</span><span class='line'>    float rho =   atan(ax/sqrt(pow(ay,2)+pow(az,2)))*(57.2957795129); //57.2957795129 degrees per rad  
</span><span class='line'>    float phi =   atan(ay/sqrt(pow(ax,2)+pow(az,2)))*(57.2957795129);  
</span><span class='line'>    float theta = atan(sqrt(pow(ay,2)+pow(ax,2))/az)*(57.2957795129);  
</span><span class='line'>
</span><span class='line'>    switch (a)
</span><span class='line'>    {
</span><span class='line'>      case 1:
</span><span class='line'>        return rho;
</span><span class='line'>        break;
</span><span class='line'>      case 2:
</span><span class='line'>        return phi;
</span><span class='line'>        break;
</span><span class='line'>      case 3:
</span><span class='line'>        return theta;
</span><span class='line'>        break;
</span><span class='line'>      default:        
</span><span class='line'>        break;
</span><span class='line'>    }
</span><span class='line'>    return 0;
</span><span class='line'>  
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>void autoZeroCalibration(int pfx, int pfy, int pfz)
</span><span class='line'>{
</span><span class='line'>    //if ((pfx &lt; minx)||(pfy &lt; miny)||(pfz &lt; minz)||(pfx > maxx)||(pfy > maxy)||(pfz > maxz)) {
</span><span class='line'>     // autozero calibration
</span><span class='line'>     if (pfx &lt; minx) minx = pfx;
</span><span class='line'>     if (pfy &lt; miny) miny = pfy;
</span><span class='line'>     if (pfz &lt; minz) minz = pfz;
</span><span class='line'>  
</span><span class='line'>     if (pfx > maxx) maxx = pfx;
</span><span class='line'>     if (pfy > maxy) maxy = pfy;
</span><span class='line'>     if (pfz > maxz) maxz = pfz;
</span><span class='line'>    
</span><span class='line'>     g0x = ((maxx - minx)/2)+minx;
</span><span class='line'>     g0y = ((maxy - miny)/2)+miny;
</span><span class='line'>     g0z = ((maxz - minz)/2)+minz;
</span><span class='line'>     
</span><span class='line'>     //printValues();
</span><span class='line'>  //}
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>////////////////////////////////////
</span><span class='line'>//// Print functions
</span><span class='line'>//////////////////////////////////
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>//void lcdPrintError(char *msg)
</span><span class='line'>//{
</span><span class='line'>//  lcdSerial.print("err:");
</span><span class='line'>//  lcdSerial.print(msg);
</span><span class='line'>//}
</span><span class='line'>
</span><span class='line'>void lcdPrint(char *msg)
</span><span class='line'>{
</span><span class='line'>  //lcdSerial.print(millis());
</span><span class='line'>  //lcdSerial.print(":");
</span><span class='line'> // lcdSerial.print(msg);
</span><span class='line'>  
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>//void lcdPrintInt(long i)
</span><span class='line'>//{
</span><span class='line'>//  lcdSerial.print(i, DEC);
</span><span class='line'>//}
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>//void lcdPrintHex(byte *hex, int size) 
</span><span class='line'>//{
</span><span class='line'>//  for(int i=0;i&lt;size;i++)
</span><span class='line'>//  {
</span><span class='line'>    //lcdPrintHex(hex[i]);
</span><span class='line'>//  }
</span><span class='line'>//}
</span><span class='line'>
</span><span class='line'>void lcdPrintBuffer(byte *hex, int size)
</span><span class='line'>{
</span><span class='line'>  //lcdPrintHex(hex,size);
</span><span class='line'>  //lcdPrintBuffer(hex,size,"buf");
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>//void lcdPrintBuffer(byte *hex, int size, char *msg)
</span><span class='line'>//{
</span><span class='line'>  
</span><span class='line'>  //int i = 0;
</span><span class='line'>  //while (i&lt;size) {    
</span><span class='line'>    //lcdSerial.print(msg);
</span><span class='line'>    //lcdSerial.print(" ");
</span><span class='line'>    //lcdSerial.print(i);
</span><span class='line'>    //lcdSerial.print("-");
</span><span class='line'>    //lcdSerial.print(i+7);
</span><span class='line'>    //lcdSerial.print("\r\n");
</span><span class='line'>    //int len = min(size-i,8);
</span><span class='line'>    //lcdPrintHex(hex+i,len);
</span><span class='line'>    //lcdSerial.print("\r\n");
</span><span class='line'>    //i=i+8;
</span><span class='line'>  //}
</span><span class='line'> // lcdSerial.print("\r\n");
</span><span class='line'>//}
</span><span class='line'>
</span><span class='line'>//void lcdPrintHex(byte hex) 
</span><span class='line'>//{
</span><span class='line'>//  lcdSerial.print((hex&0xF0)>>4,HEX);
</span><span class='line'>//  lcdSerial.print((hex&0x0F),HEX);
</span><span class='line'>//}</span>

This is the java gui I built to test the implementation

java gui

The DEV-08165 is a Serial USB Board from Sparkfun. I use it to get logs from the Arduino, the logs are outputed in serial form on pin 6 , because the serial port (USART) on the ATmega is being used for the XBee communication. The DEV-8772 is the board to program the Arduino Pro Mini, the pro mini does have an USB connector on board like other Arduinos, you need the DEV-8722 to program it/power it

Reference

Example of XBee API Frames

Some examples of XBee API Frames.

Modem status frame

7E 00 02 8A 06 6F

7E    : API Frame
00 02 : Length
8A    : Modem status
06    : Coordinator started
6F    : checksum FF – ((8A +06) & FF) = 6F

AT Command API Frame: MY

frame format

7e 00 04 08 52 4D 59 FF

7E    : API Frame
00 02 : Length
08    : AT Command Frame id
52    : Frame id
4d 59 : MY (4d 59) (4d ⇒ M, 59 ⇒ Y) Get the 16-bit network address of the module.
FF    : checksum ff = ff – ((08+52+4d+59) & ff)

AT Command Response: MY

command response frame structure
7e 00 07 88 52 4d 59 00
00 00 7f

7E    : API Frame
00 07 : Length
88    : AT Command Response API Identifier
52    : Frame id
4d 59 : MY (4d 59) (4d ⇒ M, 59 ⇒ Y) Get the 16-bit network address of the module.
00    : Status 0=OK
00 00 : MY value, 00 000 not set
7f    : checksum ff = ff – ((08+52+4d+59) & ff)

Explicit Addressing Zigbee Command Frame:

7E 00 1D 11 01 00 13 A2 00
40 3E 25 75 00 00 01 01 04
02 01 04 00 00 18 01 01 00
00 00 29 63 CE 9F

7E                         : Start frame
00 1D                      : Length (29 bytes)
11                         : explicit addressing transmit
01                         : Frame id
00 13 A2 00 40 3E 25 75    : 64 bit address
00 00                      : 16 bit address
01                         : source endpoint
01                         : destination endpoint
04 02                      : cluster id (temperature measurement cluster id/ Measurement and sensing functional domain)
01 04                      : profile id (home automation profile)
00                         : broadcast radius
00                         : options
18 01 01 00 00 00 29 63 CE : payload
9F                         : checksum

Let’s analyze the payload

18 01 01 00 00 00 29 63
CE

18 : // 00011000 0×18 / general command = 00/ manufacturer specific = 0/ direction =1/ disable default 
/ reserved = 000
01: transaction sequence
01: read response
00 00: attribute identifier
(temperature)
00: status success
29: attribute data type = 29 signed 16 bit integer
63 CE: temp value (25550 / 100)

References:


  1. XBee® & XBee-PRO® ZB ZigBee® PRO RF Modules

  2. xbee manual

  3. What is API (Application Programming Interface) Mode and how does it work?

  4. Zigbee specification

  5. Zigbee Home Automation Public Application Profile

  6. Zigbee Cluster Library

How to Display Sidebar in Single Post in WordPress 1.5 / 2.0 / 2.7.x Default Kubrick Theme

I found this great tip
How To Display Sidebar in Single Post in WordPress 1.5 / 2.0 Default Kubrick Theme
.

The only problem is that the code that you should add is not properly shown in the post. He just copied the xml code verbatim in the post without escaping it and the browser doesn’t display it properly. So I’m reproducing it here for your convenience.

  1. Go to the theme editor. Appearance ⇒ Editor
  2. Click on Theme Files ⇒ Templates ⇒ Single post (single.php)
  3. Change the class of the first div to be “narrowcolumn” instead of “widecolumn”
  4. That is, replace:

    1
    

    1
    <span class='line'>&lt;div id="content" class="widecolumn">&lt;/pre> with &lt;pre lang="xml">&lt;div id="content" class="narrowcolumn"></span>

  5. Add a call to get_sidebar() at the end just before get_footer()
  6. That is, add the following line:

    1
    

    1
    <span class='line'>&lt;?php get_sidebar(); ?></span>

    before this line:

    1
    

    1
    <span class='line'>&lt;?php get_footer(); ?></span>

    Hope this helps. Remember that it was Angsuman Chakraborty who came up with the solution. I just merely reproduced it here because I noticed that xml code in the original post is not readable.

    Force Directed Layout in NetBeans

    I just came up with the idea of reproducing the GraphView demo I saw in prefuse by using the Netbeans Visual Library API.

    The GraphView demo uses a Force Directed Layout algorithm to dinamically position the nodes on the screen. It’s really fast and cool. Download prefuse and experiment with it by yourself.

    I wanted to achieve something similiar with the Visual Library and I succeed up to a point. The force based layout algorithm that I implemented is much simpler that the used in prefuse, so there is no spring-like movement. It looks way cooler with springs. It just uses repulsion between nodes and attraction between connected nodes.

    There is also some performance issues with the Visual Library as well, the performance is not what I expected but this is maybe due to how I use the library. Or just maybe it’s just because the implementation of the layout algorithm is not as efficient as it should be. If anybody knows of a better way of using it please leave a comment in the blog.

    I should warn you before that this is just a proof-of-concept on how to get a minimum force based layout algorithm working with Netbeans Visual Library. This is a starting point, it don’t think the algorithm is usable for any non-trivial app app in this state. But from here you can get the idea on how to implement your own dynamic layout (force-based or not).

    This is a video of the Force Directed Layout in action:

    Now let’s go and explain how I did it.

    First you need a TopComponent to show the stuff.

    /*
     *   DynamicLayoutDemoTopComponent.java
     *
     *   Copyright (c) 2009 Ruben Laguna <ruben.laguna at gmail.com>. All rights reserved.
     *
     *   This program is free software: you can redistribute it and/or modify
     *   it under the terms of the GNU General Public License as published by
     *   the Free Software Foundation, either version 3 of the License, or
     *   (at your option) any later version.
     *
     *   This program is distributed in the hope that it will be useful,
     *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *   GNU General Public License for more details.
     *
     *   You should have received a copy of the GNU General Public License
     *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    package com.rubenlaguna;
    
    import java.awt.BorderLayout;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    import java.util.logging.Logger;
    import javax.swing.JComponent;
    import org.openide.util.NbBundle;
    import org.openide.windows.TopComponent;
    import org.openide.windows.WindowManager;
    //import org.openide.util.ImageUtilities;
    import org.netbeans.api.settings.ConvertAsProperties;
    import org.netbeans.api.visual.graph.GraphScene;
    import org.netbeans.api.visual.graph.layout.GridGraphLayout;
    import org.netbeans.api.visual.layout.LayoutFactory;
    import org.netbeans.api.visual.layout.SceneLayout;
    
    /**
     * Top component which displays something.
     */
    @ConvertAsProperties(dtd = "-//com.rubenlaguna//DynamicLayoutDemo//EN",
    autostore = false)
    public final class DynamicLayoutDemoTopComponent extends TopComponent implements Runnable {
    
        private static DynamicLayoutDemoTopComponent instance;
        /** path to the icon used by the component and its open action */
    //    static final String ICON_PATH = "SET/PATH/TO/ICON/HERE";
        private static final String PREFERRED_ID = "DynamicLayoutDemoTopComponent";
        private GraphSceneImpl2 scene;
        private JComponent view;
        private static ScheduledExecutorService EX = Executors.newSingleThreadScheduledExecutor();
        private SceneLayout sceneGraphLayout;
    
        public DynamicLayoutDemoTopComponent() {
            initComponents();
            setName(NbBundle.getMessage(DynamicLayoutDemoTopComponent.class, "CTL_DynamicLayoutDemoTopComponent"));
            setToolTipText(NbBundle.getMessage(DynamicLayoutDemoTopComponent.class, "HINT_DynamicLayoutDemoTopComponent"));
    //        setIcon(ImageUtilities.loadImage(ICON_PATH, true));
            scene = new GraphSceneImpl2();
            view = scene.createView();
            jScrollPane1.setViewportView(view);
    
            add(scene.createSatelliteView(), BorderLayout.WEST);
            scene.addNode("1");
            scene.addNode("2");
            scene.addNode("3");
            scene.addNode("4");
            scene.addNode("5");
            scene.addNode("6");
            scene.addNode("7");
            scene.addNode("8");
            scene.addNode("9");
            scene.addNode("10");
            scene.addNode("11");
            scene.addNode("12");
            scene.addNode("13");
            scene.addNode("14");
            scene.addNode("15");
            scene.addNode("16");
            scene.addNode("17");
            scene.addNode("18");
            scene.addNode("19");
            scene.addNode("20");
            scene.addNode("21");
            scene.addNode("22");
            scene.addNode("23");
            scene.addNode("24");
            scene.addNode("25");
    
    
    
            scene.addEdge("1", "2");
            scene.addEdge("2", "3");
            scene.addEdge("3", "4");
            scene.addEdge("4", "5");
    
            scene.addEdge("6", "7");
            scene.addEdge("7", "8");
            scene.addEdge("8", "9");
            scene.addEdge("9", "10");
    
            scene.addEdge("11", "12");
            scene.addEdge("12", "13");
            scene.addEdge("13", "14");
            scene.addEdge("14", "15");
    
            scene.addEdge("16", "17");
            scene.addEdge("17", "18");
            scene.addEdge("18", "19");
            scene.addEdge("19", "20");
    
            scene.addEdge("21", "22");
            scene.addEdge("22", "23");
            scene.addEdge("23", "24");
            scene.addEdge("24", "25");
    
            scene.addEdge("1", "6");
            scene.addEdge("2", "7");
            scene.addEdge("3", "8");
            scene.addEdge("4", "9");
            scene.addEdge("5", "10");
    
            scene.addEdge("6","11");
            scene.addEdge("7","12");
            scene.addEdge("8","13");
            scene.addEdge("9","14");
            scene.addEdge("10","15");
    
            scene.addEdge("11","16");
            scene.addEdge("12","17");
            scene.addEdge("13","18");
            scene.addEdge("14","19");
            scene.addEdge("15","20");
    
            scene.addEdge("16","21");
            scene.addEdge("17","22");
            scene.addEdge("18","23");
            scene.addEdge("19","24");
            scene.addEdge("20","25");
    
            GridGraphLayout<String, String> graphLayout = new GridGraphLayout<String, String>();
            //sceneGraphLayout = LayoutFactory.createSceneGraphLayout(scene, graphLayout);
            //sceneGraphLayout.invokeLayout();
            ForceDirectedLayout<String, String> graphLayout2 = new ForceDirectedLayout<String, String>();
            graphLayout.setAnimated(false);
            sceneGraphLayout = LayoutFactory.createSceneGraphLayout(scene, graphLayout2);
            EX.schedule(this, 50, TimeUnit.MILLISECONDS);
        }
    
        /** This method is called from within the constructor to
         * initialize the form.
         * WARNING: Do NOT modify this code. The content of this method is
         * always regenerated by the Form Editor.
         */
        // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
        private void initComponents() {
    
            jScrollPane1 = new javax.swing.JScrollPane();
    
            setLayout(new java.awt.BorderLayout());
            add(jScrollPane1, java.awt.BorderLayout.CENTER);
        }// </editor-fold>//GEN-END:initComponents
        // Variables declaration - do not modify//GEN-BEGIN:variables
        private javax.swing.JScrollPane jScrollPane1;
        // End of variables declaration//GEN-END:variables
    
        /**
         * Gets default instance. Do not use directly: reserved for *.settings files only,
         * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
         * To obtain the singleton instance, use {@link #findInstance}.
         */
        public static synchronized DynamicLayoutDemoTopComponent getDefault() {
            if (instance == null) {
                instance = new DynamicLayoutDemoTopComponent();
            }
            return instance;
        }
    
        /**
         * Obtain the DynamicLayoutDemoTopComponent instance. Never call {@link #getDefault} directly!
         */
        public static synchronized DynamicLayoutDemoTopComponent findInstance() {
            TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
            if (win == null) {
                Logger.getLogger(DynamicLayoutDemoTopComponent.class.getName()).warning(
                        "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system.");
                return getDefault();
            }
            if (win instanceof DynamicLayoutDemoTopComponent) {
                return (DynamicLayoutDemoTopComponent) win;
            }
            Logger.getLogger(DynamicLayoutDemoTopComponent.class.getName()).warning(
                    "There seem to be multiple components with the '" + PREFERRED_ID +
                    "' ID. That is a potential source of errors and unexpected behavior.");
            return getDefault();
        }
    
        @Override
        public int getPersistenceType() {
            return TopComponent.PERSISTENCE_NEVER;
        }
    
        @Override
        public void componentOpened() {
            // TODO add custom code on component opening
        }
    
        @Override
        public void componentClosed() {
            // TODO add custom code on component closing
        }
    
        void writeProperties(java.util.Properties p) {
            // better to version settings since initial version as advocated at
            // http://wiki.apidesign.org/wiki/PropertyFiles
            p.setProperty("version", "1.0");
            // TODO store your settings
        }
    
        Object readProperties(java.util.Properties p) {
            DynamicLayoutDemoTopComponent singleton = DynamicLayoutDemoTopComponent.getDefault();
            singleton.readPropertiesImpl(p);
            return singleton;
        }
    
        private void readPropertiesImpl(java.util.Properties p) {
            String version = p.getProperty("version");
            // TODO read your settings according to their version
        }
    
        @Override
        protected String preferredID() {
            return PREFERRED_ID;
        }
    
        public void run() {
    
            sceneGraphLayout.invokeLayout();
            EX.schedule(this, 50, TimeUnit.MILLISECONDS);
        }
    }
    
    

    This TopComponent does a bunch of things:


    1. sets up the GraphScene

    2. adds some nodes and edges to it (forming a grid)

    3. Instantiate a ForceDirectedLayout and generate a SceneLayout out of it

    4. Creates an Executor that will do SceneLayout.invokeLayout every 50 milliseconds.
    5. The GraphScene that I use is very simple. It’s based on GraphScene.StringGraph:

    /*
     *   GraphSceneImpl2.java
     *
     *   Copyright (c) 2009 Ruben Laguna <ruben.laguna at gmail.com>. All rights reserved.
     *
     *   This program is free software: you can redistribute it and/or modify
     *   it under the terms of the GNU General Public License as published by
     *   the Free Software Foundation, either version 3 of the License, or
     *   (at your option) any later version.
     *
     *   This program is distributed in the hope that it will be useful,
     *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *   GNU General Public License for more details.
     *
     *   You should have received a copy of the GNU General Public License
     *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    package com.rubenlaguna;
    
    import org.netbeans.api.visual.anchor.AnchorFactory;
    import org.netbeans.api.visual.graph.GraphScene;
    import org.netbeans.api.visual.widget.ConnectionWidget;
    import org.netbeans.api.visual.widget.LabelWidget;
    import org.netbeans.api.visual.widget.LayerWidget;
    import org.netbeans.api.visual.widget.Widget;
    
    /**
     *
     * @author ecerulm
     */
    public class GraphSceneImpl2 extends GraphScene.StringGraph {
    
        private int edgeID = 0;
        private LayerWidget mainLayer;
        private LayerWidget connectionLayer;
    
        public GraphSceneImpl2() {
            mainLayer = new LayerWidget(this);
            connectionLayer = new LayerWidget(this);
            addChild(mainLayer);
            addChild(connectionLayer);
        }
    
        @Override
        protected Widget attachNodeWidget(String node) {
            LabelWidget w = new LabelWidget(this, node);
            mainLayer.addChild(w);
            return w;
        }
    
        @Override
        protected Widget attachEdgeWidget(String edge) {
            ConnectionWidget connectionWidget = new ConnectionWidget(this);
            connectionLayer.addChild(connectionWidget);
            return connectionWidget;
        }
    
        @Override
        protected void attachEdgeSourceAnchor(String edge, String oldSourceNode, String sourceNode) {
           ((ConnectionWidget) findWidget (edge)).setSourceAnchor (AnchorFactory.createRectangularAnchor (findWidget (sourceNode)));
        }
    
        @Override
        protected void attachEdgeTargetAnchor(String edge, String oldTargetNode, String targetNode) {
            ((ConnectionWidget) findWidget (edge)).setTargetAnchor (AnchorFactory.createRectangularAnchor (findWidget (targetNode)));
        }
    
        public void addEdge(String source, String target) {
            String id = "edge" + (edgeID++);
            addEdge(id);
            setEdgeSource(id, source);
            setEdgeTarget(id, target);
    
        }
    }
    

    And finally the ForceDirectLayout:

    /*
     *   ForceDirectedLayout.java
     *
     *   Copyright (c) 2009 Ruben Laguna <ruben.laguna at gmail.com>. All rights reserved.
     *
     *   This program is free software: you can redistribute it and/or modify
     *   it under the terms of the GNU General Public License as published by
     *   the Free Software Foundation, either version 3 of the License, or
     *   (at your option) any later version.
     *
     *   This program is distributed in the hope that it will be useful,
     *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *   GNU General Public License for more details.
     *
     *   You should have received a copy of the GNU General Public License
     *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    package com.rubenlaguna;
    
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    import org.netbeans.api.visual.graph.layout.GraphLayout;
    import org.netbeans.api.visual.graph.layout.UniversalGraph;
    import org.netbeans.api.visual.model.ObjectScene;
    import org.netbeans.api.visual.widget.Widget;
    
    /**
     *
     * @author ecerulm
     */
    public class ForceDirectedLayout<N, E> extends GraphLayout<N, E> {
    
        private Random random = new Random();
        private boolean firstTime = true;
    
        @Override
        protected void performGraphLayout(UniversalGraph<N, E> graph) {
            ObjectScene scene = graph.getScene();
            Collection<N> allNodes = graph.getNodes();
            Map<N, Point> forceForEachNode = new HashMap<N, Point>();
            
    
    
            if (firstTime) {
                List<Point> list = new ArrayList<Point>();
                for (Iterator<N> it = allNodes.iterator(); it.hasNext();) {
                    N object = it.next();
                    Point point = new Point(random.nextInt(600), random.nextInt(600));
                    list.add(point);
                }
    
    
                for (int i = 0; i < (list.size() / 2); i++) {
                    Point p = list.get(i);
    
                    for (int j = i + 1; j < list.size(); j++) {
                        Point p2 = list.get(j);
                        double distance = Math.sqrt(Math.pow(p2.x - p.x, 2) + Math.pow(p2.y - p.y, 2));
                        if (distance < 40) {
                            p2.translate(30, 30);
                        }
                    }
    
                }
                ;
    
                for (Iterator<N> it = allNodes.iterator(); it.hasNext();) {
                    N object = it.next();
                    Point p = list.remove(0);
                    setResolvedNodeLocation(graph, object, p);
                    scene.findWidget(object).setPreferredLocation(p);
                }
                firstTime = false;
    
                return;
            }
    
            //initialize forceForEachNode map
            for (Iterator<N> it = allNodes.iterator(); it.hasNext();) {
                N object = it.next();
                forceForEachNode.put(object, new Point(0, 0));
            }
    
    
            //Calculate repulsion forces
            for (Iterator<N> it = allNodes.iterator(); it.hasNext();) {
                N thisNode = it.next();
                HashSet<N> allOtherNodes = new HashSet<N>(allNodes);
                allOtherNodes.remove(thisNode);
                for (Iterator<N> it1 = allOtherNodes.iterator(); it1.hasNext();) {
                    N otherNode = it1.next();
    
    
                    Point thisWidget = scene.findWidget(thisNode).getLocation();
                    Point otherWidget = scene.findWidget(otherNode).getLocation();
                    if ((null != thisWidget) && (null != otherWidget)) {
                        int x = thisWidget.x - otherWidget.x;
                        int y = thisWidget.y - otherWidget.y;
                        double sum = Math.pow(x, 2) + Math.pow(y, 2);
                        double distance = Math.sqrt(sum);
                        double minDist = 50.0;
                        x = ((int) (x * (minDist / distance))); //inversely proportional to the distance
                        y = ((int) (y * (minDist / distance)));
                        //Point force = new Point(x,y);
                        Point currentForce = forceForEachNode.get(thisNode);
                        currentForce.translate(x, y);
                    }
                }
            }
    
            // get got all the repulsion forces.
    
            //now the attraction forces.
            for (Iterator<N> it = allNodes.iterator(); it.hasNext();) {
                N thisNode = it.next();
                for (E edge : graph.findNodeEdges(thisNode, true, false)) {
                    N otherNode = graph.getEdgeTarget(edge);
                    if (otherNode != null) {
                        Point thisWidget = scene.findWidget(thisNode).getLocation();
                        Point otherWidget = scene.findWidget(otherNode).getLocation();
                        if ((null != thisWidget) && (null != otherWidget)) {
    
                            int x = thisWidget.x - otherWidget.x;
                            int y = thisWidget.y - otherWidget.y;
                            double sum = Math.pow(x, 2) + Math.pow(y, 2);
                            double distance = Math.sqrt(sum);
                            double minDist = 50.0;
                            x = -((int) (x * (distance / 30))); //directly proportional to the distance
                            y = -((int) (y * (distance / 30)));
    
                            //Point force = new Point(x,y);
                            Point currentForce = forceForEachNode.get(thisNode);
                            currentForce.translate(x, y);
                            currentForce = forceForEachNode.get(otherNode);
                            currentForce.translate(-x, -y);
                        }
                    }
                }
            }
    
            //Use the force  (silly joke)
            for (Iterator<N> it = allNodes.iterator(); it.hasNext();) {
                N object = it.next();
                Point force = forceForEachNode.get(object);
                int x = force.x / 50;
                int y = force.y / 50;
                if (x > 0) {
                    x = Math.min(x, 15);
                } else {
                    x = Math.max(x, -15);
                }
                if (y > 0) {
                    y = Math.min(y, 15);
                } else {
                    y = Math.max(y, -15);
                }
                //x = x+((int) (x * (((float)random.nextInt(5)) / 100.0)));
                //y = y+((int) (y * (((float)random.nextInt(5)) / 100.0)));
                x = x + (-3+random.nextInt(6));
                y = y + (-3+random.nextInt(6));
    
    
                Point newPosition = scene.findWidget(object).getLocation();
                if (null != newPosition) {
                    newPosition.translate(x, y);
                    setResolvedNodeLocation(graph, object, newPosition);
                }
    
            }
        }
    
        @Override
        protected void performNodesLayout(UniversalGraph<N, E> graph, Collection<N> nodes) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
    
    

    The result is shown in the picture below. Of cource, you can’t see the dinamic behaviour of this layout algorithm in the picture. You’ll have to download and execute this Netbeans Platform Application: dynamiclayoutdemo (Netbeans 6.7 M2) to see it with you own eyes.

    Reference:

    Copyright © 2015 - Ruben Laguna - Powered by Octopress