Code example to regularly report light level and temperature over Sigfox on the QW dev kit
This is a code example that demonstrates sending the light level sensor and temperature sensor output over Sigfox at regular time intervals.
The payload that is sent over the network consists of 3 bytes:
- two bytes light level reading
- one bye temperature reading.
Use this code example as a start to connect your own device over Sigfox with the Quicksand QW development kit.
main.cpp@1:b2c941af91c6, 2016-03-08 (annotated)
- Committer:
- LievenHollevoet
- Date:
- Tue Mar 08 09:48:32 2016 +0000
- Revision:
- 1:b2c941af91c6
- Parent:
- 0:9a93fff79b27
Updated repo of QW sensors to local copy.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
LievenHollevoet | 0:9a93fff79b27 | 1 | /* This program is an example application that measures the temperature and the light level |
LievenHollevoet | 0:9a93fff79b27 | 2 | * and transmits the sensor readings over the Sigfox network. |
LievenHollevoet | 0:9a93fff79b27 | 3 | * A transmission is scheduled every 15 minutes, and the user can force a transmission |
LievenHollevoet | 0:9a93fff79b27 | 4 | * by pressing the user button one. |
LievenHollevoet | 0:9a93fff79b27 | 5 | * |
LievenHollevoet | 0:9a93fff79b27 | 6 | * The data format of the Sigfox payload is: |
LievenHollevoet | 0:9a93fff79b27 | 7 | * First two bytes of the payload: light level as unsigned 16-bit value. |
LievenHollevoet | 0:9a93fff79b27 | 8 | * Third byte of the payload: temperature as signed 8-bit value |
LievenHollevoet | 0:9a93fff79b27 | 9 | * |
LievenHollevoet | 0:9a93fff79b27 | 10 | * Open a serial console to the board to get a debug trace. |
LievenHollevoet | 0:9a93fff79b27 | 11 | * |
LievenHollevoet | 0:9a93fff79b27 | 12 | * Note: this is a very basic example that has no energy usage optimization. The controller is not put in sleep mode |
LievenHollevoet | 0:9a93fff79b27 | 13 | * in between readings/Sigfox transmissions in order to keep the code flow linear and short. |
LievenHollevoet | 0:9a93fff79b27 | 14 | * |
LievenHollevoet | 0:9a93fff79b27 | 15 | * In the current configuration, the temperature sensor is read once per second and a Sigfox transmission is scheduled every 15 minutes. |
LievenHollevoet | 0:9a93fff79b27 | 16 | * Adapt the defines TX_INTERVAL and MEASURE_INTERVAL to change these settings. |
LievenHollevoet | 0:9a93fff79b27 | 17 | */ |
LievenHollevoet | 0:9a93fff79b27 | 18 | |
LievenHollevoet | 0:9a93fff79b27 | 19 | #include "mbed.h" |
LievenHollevoet | 0:9a93fff79b27 | 20 | #include "math.h" |
LievenHollevoet | 0:9a93fff79b27 | 21 | #include "LinearTempSensor.h" |
LievenHollevoet | 0:9a93fff79b27 | 22 | #include "VCNL4010.h" |
LievenHollevoet | 0:9a93fff79b27 | 23 | |
LievenHollevoet | 0:9a93fff79b27 | 24 | #define SER_BUFFER_SIZE 32 |
LievenHollevoet | 0:9a93fff79b27 | 25 | |
LievenHollevoet | 0:9a93fff79b27 | 26 | // Interval in minutes for scheduled Tx |
LievenHollevoet | 0:9a93fff79b27 | 27 | #define TX_INTERVAL 15 |
LievenHollevoet | 0:9a93fff79b27 | 28 | |
LievenHollevoet | 0:9a93fff79b27 | 29 | // Temperature measure interval in seconds |
LievenHollevoet | 0:9a93fff79b27 | 30 | #define MEASURE_INTERVAL 1 |
LievenHollevoet | 0:9a93fff79b27 | 31 | |
LievenHollevoet | 0:9a93fff79b27 | 32 | /* The 4 onboard LEDs */ |
LievenHollevoet | 0:9a93fff79b27 | 33 | DigitalOut LED_0 (PB_6); |
LievenHollevoet | 0:9a93fff79b27 | 34 | DigitalOut LED_1 (PA_7); |
LievenHollevoet | 0:9a93fff79b27 | 35 | DigitalOut LED_2 (PA_6); |
LievenHollevoet | 0:9a93fff79b27 | 36 | DigitalOut LED_3 (PA_5); |
LievenHollevoet | 0:9a93fff79b27 | 37 | |
LievenHollevoet | 0:9a93fff79b27 | 38 | /* The 2 user buttons */ |
LievenHollevoet | 0:9a93fff79b27 | 39 | InterruptIn SW1(PA_8); |
LievenHollevoet | 0:9a93fff79b27 | 40 | InterruptIn SW2(PB_10); |
LievenHollevoet | 0:9a93fff79b27 | 41 | |
LievenHollevoet | 0:9a93fff79b27 | 42 | /* Proximity and ambient light sensor*/ |
LievenHollevoet | 0:9a93fff79b27 | 43 | VCNL40x0 VCNL4010(PB_9, PB_8, VCNL40x0_ADDRESS); // SDA, SCL pin and I2C address |
LievenHollevoet | 0:9a93fff79b27 | 44 | |
LievenHollevoet | 0:9a93fff79b27 | 45 | /*Temperature sensor */ |
LievenHollevoet | 0:9a93fff79b27 | 46 | LinearTempSensor sensor(PA_0, 40); |
LievenHollevoet | 0:9a93fff79b27 | 47 | |
LievenHollevoet | 0:9a93fff79b27 | 48 | /* Ticker for scheduled transmissions */ |
LievenHollevoet | 0:9a93fff79b27 | 49 | Ticker tTX; |
LievenHollevoet | 0:9a93fff79b27 | 50 | Ticker tSense; |
LievenHollevoet | 0:9a93fff79b27 | 51 | |
LievenHollevoet | 0:9a93fff79b27 | 52 | /* Function prototypes */ |
LievenHollevoet | 0:9a93fff79b27 | 53 | void sw1interrupt(); |
LievenHollevoet | 0:9a93fff79b27 | 54 | void sw2interrupt(); |
LievenHollevoet | 0:9a93fff79b27 | 55 | void sertmout(); |
LievenHollevoet | 0:9a93fff79b27 | 56 | bool read_acc(int& x, int& y, int& z); |
LievenHollevoet | 0:9a93fff79b27 | 57 | bool modem_command_check_ok(char * command); |
LievenHollevoet | 0:9a93fff79b27 | 58 | void modem_setup(); |
LievenHollevoet | 0:9a93fff79b27 | 59 | void txData(); |
LievenHollevoet | 0:9a93fff79b27 | 60 | void dataScheduledTX(); |
LievenHollevoet | 0:9a93fff79b27 | 61 | void senseTemperature(); |
LievenHollevoet | 0:9a93fff79b27 | 62 | |
LievenHollevoet | 0:9a93fff79b27 | 63 | bool ser_timeout = false; |
LievenHollevoet | 0:9a93fff79b27 | 64 | bool handleIRQ1 = false; |
LievenHollevoet | 0:9a93fff79b27 | 65 | |
LievenHollevoet | 0:9a93fff79b27 | 66 | /* Serial port over USB */ |
LievenHollevoet | 0:9a93fff79b27 | 67 | Serial pc(USBTX, USBRX); |
LievenHollevoet | 0:9a93fff79b27 | 68 | |
LievenHollevoet | 0:9a93fff79b27 | 69 | /* Serial connection to sigfox modem */ |
LievenHollevoet | 0:9a93fff79b27 | 70 | Serial modem(PA_9, PA_10); |
LievenHollevoet | 0:9a93fff79b27 | 71 | |
LievenHollevoet | 0:9a93fff79b27 | 72 | int main() |
LievenHollevoet | 0:9a93fff79b27 | 73 | { |
LievenHollevoet | 0:9a93fff79b27 | 74 | /* Storage for VCNL4010 readout */ |
LievenHollevoet | 0:9a93fff79b27 | 75 | unsigned char ID=0, Current=0; |
LievenHollevoet | 0:9a93fff79b27 | 76 | //unsigned int ProxiValue=0, AmbiValue=0; |
LievenHollevoet | 0:9a93fff79b27 | 77 | |
LievenHollevoet | 0:9a93fff79b27 | 78 | /* Variables that will store analog temperature sensor reading */ |
LievenHollevoet | 0:9a93fff79b27 | 79 | //float Tav, To; |
LievenHollevoet | 0:9a93fff79b27 | 80 | |
LievenHollevoet | 0:9a93fff79b27 | 81 | /* Setup TD120x */ |
LievenHollevoet | 0:9a93fff79b27 | 82 | wait(3); |
LievenHollevoet | 0:9a93fff79b27 | 83 | modem_setup(); |
LievenHollevoet | 0:9a93fff79b27 | 84 | |
LievenHollevoet | 0:9a93fff79b27 | 85 | /* Turn off all LED */ |
LievenHollevoet | 0:9a93fff79b27 | 86 | LED_0 = 1; |
LievenHollevoet | 0:9a93fff79b27 | 87 | LED_1 = 1; |
LievenHollevoet | 0:9a93fff79b27 | 88 | LED_2 = 1; |
LievenHollevoet | 0:9a93fff79b27 | 89 | LED_3 = 1; |
LievenHollevoet | 0:9a93fff79b27 | 90 | |
LievenHollevoet | 0:9a93fff79b27 | 91 | /* Setup button interrupts */ |
LievenHollevoet | 0:9a93fff79b27 | 92 | SW2.fall(&sw2interrupt); |
LievenHollevoet | 0:9a93fff79b27 | 93 | SW1.fall(&sw1interrupt); |
LievenHollevoet | 0:9a93fff79b27 | 94 | |
LievenHollevoet | 0:9a93fff79b27 | 95 | /* Read VCNL40x0 product ID revision register */ |
LievenHollevoet | 0:9a93fff79b27 | 96 | VCNL4010.ReadID (&ID); |
LievenHollevoet | 0:9a93fff79b27 | 97 | pc.printf("\nVCNL4010 Product ID Revision Register: %d", ID); |
LievenHollevoet | 0:9a93fff79b27 | 98 | |
LievenHollevoet | 0:9a93fff79b27 | 99 | VCNL4010.SetCurrent (20); // Set current to 200mA |
LievenHollevoet | 0:9a93fff79b27 | 100 | VCNL4010.ReadCurrent (&Current); // Read back IR LED current |
LievenHollevoet | 0:9a93fff79b27 | 101 | pc.printf("\nVCNL4010 IR LED Current: %d\n\n", Current); |
LievenHollevoet | 0:9a93fff79b27 | 102 | |
LievenHollevoet | 0:9a93fff79b27 | 103 | // Sense temperature for the first time |
LievenHollevoet | 0:9a93fff79b27 | 104 | senseTemperature(); |
LievenHollevoet | 0:9a93fff79b27 | 105 | |
LievenHollevoet | 0:9a93fff79b27 | 106 | wait_ms(3000); // wait 3s (only for display) |
LievenHollevoet | 0:9a93fff79b27 | 107 | |
LievenHollevoet | 0:9a93fff79b27 | 108 | tTX.attach(&dataScheduledTX, TX_INTERVAL*60); // Attach the timer for TX |
LievenHollevoet | 0:9a93fff79b27 | 109 | tSense.attach(&senseTemperature, MEASURE_INTERVAL); // Attach the timer for sensing the temperature |
LievenHollevoet | 0:9a93fff79b27 | 110 | |
LievenHollevoet | 0:9a93fff79b27 | 111 | while(1) |
LievenHollevoet | 0:9a93fff79b27 | 112 | { |
LievenHollevoet | 0:9a93fff79b27 | 113 | /* |
LievenHollevoet | 0:9a93fff79b27 | 114 | // VCNL4010 reading |
LievenHollevoet | 0:9a93fff79b27 | 115 | VCNL4010.ReadProxiOnDemand (&ProxiValue); // read prox value on demand |
LievenHollevoet | 0:9a93fff79b27 | 116 | VCNL4010.ReadAmbiOnDemand (&AmbiValue); // read ambi value on demand |
LievenHollevoet | 0:9a93fff79b27 | 117 | // MCP9700 reading |
LievenHollevoet | 0:9a93fff79b27 | 118 | Tav = sensor.GetAverageTemp(); |
LievenHollevoet | 0:9a93fff79b27 | 119 | To = sensor.GetLatestTemp(); |
LievenHollevoet | 0:9a93fff79b27 | 120 | |
LievenHollevoet | 0:9a93fff79b27 | 121 | pc.printf("\n\rVCNL4010 report: Proximity: %5.0i cts, Ambient light: %5.0i cts, Illuminance: %7.2f lx\n\rMCP9700 report: Average Temp: %.2f %cC, Latest Temp: %.2f %cC", ProxiValue, AmbiValue, AmbiValue/4.0, Tav, 176, To, 176); |
LievenHollevoet | 0:9a93fff79b27 | 122 | wait_ms(5000); |
LievenHollevoet | 0:9a93fff79b27 | 123 | */ |
LievenHollevoet | 0:9a93fff79b27 | 124 | |
LievenHollevoet | 0:9a93fff79b27 | 125 | if (handleIRQ1) { |
LievenHollevoet | 0:9a93fff79b27 | 126 | txData(); |
LievenHollevoet | 0:9a93fff79b27 | 127 | handleIRQ1 = false; |
LievenHollevoet | 0:9a93fff79b27 | 128 | } |
LievenHollevoet | 0:9a93fff79b27 | 129 | } |
LievenHollevoet | 0:9a93fff79b27 | 130 | } |
LievenHollevoet | 0:9a93fff79b27 | 131 | |
LievenHollevoet | 0:9a93fff79b27 | 132 | void modem_setup() |
LievenHollevoet | 0:9a93fff79b27 | 133 | { |
LievenHollevoet | 0:9a93fff79b27 | 134 | /* Reset to factory defaults */ |
LievenHollevoet | 0:9a93fff79b27 | 135 | if(modem_command_check_ok("AT&F")) |
LievenHollevoet | 0:9a93fff79b27 | 136 | { |
LievenHollevoet | 0:9a93fff79b27 | 137 | pc.printf("Factory reset succesfull\r\n"); |
LievenHollevoet | 0:9a93fff79b27 | 138 | } |
LievenHollevoet | 0:9a93fff79b27 | 139 | else |
LievenHollevoet | 0:9a93fff79b27 | 140 | { |
LievenHollevoet | 0:9a93fff79b27 | 141 | pc.printf("Factory reset TD120x failed\r\n"); |
LievenHollevoet | 0:9a93fff79b27 | 142 | } |
LievenHollevoet | 0:9a93fff79b27 | 143 | /* Disable local echo */ |
LievenHollevoet | 0:9a93fff79b27 | 144 | modem.printf("ATE0\n"); |
LievenHollevoet | 0:9a93fff79b27 | 145 | if(modem_command_check_ok("ATE0")) |
LievenHollevoet | 0:9a93fff79b27 | 146 | { |
LievenHollevoet | 0:9a93fff79b27 | 147 | pc.printf("Local echo disabled\r\n"); |
LievenHollevoet | 0:9a93fff79b27 | 148 | } |
LievenHollevoet | 0:9a93fff79b27 | 149 | /* Write to mem */ |
LievenHollevoet | 0:9a93fff79b27 | 150 | if(modem_command_check_ok("AT&W")) |
LievenHollevoet | 0:9a93fff79b27 | 151 | { |
LievenHollevoet | 0:9a93fff79b27 | 152 | pc.printf("Settings saved!\r\n"); |
LievenHollevoet | 0:9a93fff79b27 | 153 | } |
LievenHollevoet | 0:9a93fff79b27 | 154 | } |
LievenHollevoet | 0:9a93fff79b27 | 155 | |
LievenHollevoet | 0:9a93fff79b27 | 156 | bool modem_command_check_ok(char * command) |
LievenHollevoet | 0:9a93fff79b27 | 157 | { |
LievenHollevoet | 0:9a93fff79b27 | 158 | /* first clear serial data buffers */ |
LievenHollevoet | 0:9a93fff79b27 | 159 | while(modem.readable()) modem.getc(); |
LievenHollevoet | 0:9a93fff79b27 | 160 | /* Timeout for response of the modem */ |
LievenHollevoet | 0:9a93fff79b27 | 161 | Timeout tmout; |
LievenHollevoet | 0:9a93fff79b27 | 162 | ser_timeout = false; |
LievenHollevoet | 0:9a93fff79b27 | 163 | /* Buffer for incoming data */ |
LievenHollevoet | 0:9a93fff79b27 | 164 | char responsebuffer[6]; |
LievenHollevoet | 0:9a93fff79b27 | 165 | /* Flag to set when we get 'OK' response */ |
LievenHollevoet | 0:9a93fff79b27 | 166 | bool ok = false; |
LievenHollevoet | 0:9a93fff79b27 | 167 | bool error = false; |
LievenHollevoet | 0:9a93fff79b27 | 168 | /* Print command to TD120x */ |
LievenHollevoet | 0:9a93fff79b27 | 169 | modem.printf(command); |
LievenHollevoet | 0:9a93fff79b27 | 170 | /* Newline to activate command */ |
LievenHollevoet | 0:9a93fff79b27 | 171 | modem.printf("\n"); |
LievenHollevoet | 0:9a93fff79b27 | 172 | /* Wait untill serial feedback, max 3 seconds before timeout */ |
LievenHollevoet | 0:9a93fff79b27 | 173 | tmout.attach(&sertmout, 3.0); |
LievenHollevoet | 0:9a93fff79b27 | 174 | while(!modem.readable()&& ser_timeout == false); |
LievenHollevoet | 0:9a93fff79b27 | 175 | while(!ok && !ser_timeout && !error) |
LievenHollevoet | 0:9a93fff79b27 | 176 | { |
LievenHollevoet | 0:9a93fff79b27 | 177 | if(modem.readable()) |
LievenHollevoet | 0:9a93fff79b27 | 178 | { |
LievenHollevoet | 0:9a93fff79b27 | 179 | for(int i = 0; i < 5; i++) |
LievenHollevoet | 0:9a93fff79b27 | 180 | { |
LievenHollevoet | 0:9a93fff79b27 | 181 | responsebuffer[i] = responsebuffer[i+1]; |
LievenHollevoet | 0:9a93fff79b27 | 182 | } |
LievenHollevoet | 0:9a93fff79b27 | 183 | responsebuffer[5] = modem.getc(); |
LievenHollevoet | 0:9a93fff79b27 | 184 | if(responsebuffer[0] == '\r' && responsebuffer[1] == '\n' && responsebuffer[2] == 'O' && responsebuffer[3] == 'K' && responsebuffer[4] == '\r' && responsebuffer[5] == '\n' ) |
LievenHollevoet | 0:9a93fff79b27 | 185 | { |
LievenHollevoet | 0:9a93fff79b27 | 186 | ok = true; |
LievenHollevoet | 0:9a93fff79b27 | 187 | } |
LievenHollevoet | 0:9a93fff79b27 | 188 | else if(responsebuffer[0] == '\r' && responsebuffer[1] == '\n' && responsebuffer[2] == 'E' && responsebuffer[3] == 'R' && responsebuffer[4] == 'R' && responsebuffer[5] == 'O' ) |
LievenHollevoet | 0:9a93fff79b27 | 189 | { |
LievenHollevoet | 0:9a93fff79b27 | 190 | error = true; |
LievenHollevoet | 0:9a93fff79b27 | 191 | } |
LievenHollevoet | 0:9a93fff79b27 | 192 | } |
LievenHollevoet | 0:9a93fff79b27 | 193 | } |
LievenHollevoet | 0:9a93fff79b27 | 194 | tmout.detach(); |
LievenHollevoet | 0:9a93fff79b27 | 195 | return ok; |
LievenHollevoet | 0:9a93fff79b27 | 196 | } |
LievenHollevoet | 0:9a93fff79b27 | 197 | |
LievenHollevoet | 0:9a93fff79b27 | 198 | /* Button 1 ISR */ |
LievenHollevoet | 0:9a93fff79b27 | 199 | void sw1interrupt() |
LievenHollevoet | 0:9a93fff79b27 | 200 | { |
LievenHollevoet | 0:9a93fff79b27 | 201 | pc.printf("\n\rButton 1 pressed\n\r"); |
LievenHollevoet | 0:9a93fff79b27 | 202 | LED_1 = 0; |
LievenHollevoet | 0:9a93fff79b27 | 203 | handleIRQ1 = true; |
LievenHollevoet | 0:9a93fff79b27 | 204 | } |
LievenHollevoet | 0:9a93fff79b27 | 205 | |
LievenHollevoet | 0:9a93fff79b27 | 206 | /* Button 2 ISR */ |
LievenHollevoet | 0:9a93fff79b27 | 207 | void sw2interrupt() |
LievenHollevoet | 0:9a93fff79b27 | 208 | { |
LievenHollevoet | 0:9a93fff79b27 | 209 | pc.printf("\n\rButton 2 pressed\n\r"); |
LievenHollevoet | 0:9a93fff79b27 | 210 | } |
LievenHollevoet | 0:9a93fff79b27 | 211 | |
LievenHollevoet | 0:9a93fff79b27 | 212 | void dataScheduledTX() |
LievenHollevoet | 0:9a93fff79b27 | 213 | { |
LievenHollevoet | 0:9a93fff79b27 | 214 | pc.printf("\n\rScheduled Sigfox TX triggered\n\r"); |
LievenHollevoet | 0:9a93fff79b27 | 215 | LED_1 = 0; |
LievenHollevoet | 0:9a93fff79b27 | 216 | handleIRQ1 = true; |
LievenHollevoet | 0:9a93fff79b27 | 217 | } |
LievenHollevoet | 0:9a93fff79b27 | 218 | |
LievenHollevoet | 0:9a93fff79b27 | 219 | /* ISR for serial timeout */ |
LievenHollevoet | 0:9a93fff79b27 | 220 | void sertmout() |
LievenHollevoet | 0:9a93fff79b27 | 221 | { |
LievenHollevoet | 0:9a93fff79b27 | 222 | ser_timeout = true; |
LievenHollevoet | 0:9a93fff79b27 | 223 | } |
LievenHollevoet | 0:9a93fff79b27 | 224 | |
LievenHollevoet | 0:9a93fff79b27 | 225 | /* TX data over Sigfox */ |
LievenHollevoet | 0:9a93fff79b27 | 226 | void txData (){ |
LievenHollevoet | 0:9a93fff79b27 | 227 | |
LievenHollevoet | 0:9a93fff79b27 | 228 | unsigned int ambiValue = 0; |
LievenHollevoet | 0:9a93fff79b27 | 229 | int8_t tAvgByte = 0; |
LievenHollevoet | 0:9a93fff79b27 | 230 | uint16_t ambiValueShort; |
LievenHollevoet | 0:9a93fff79b27 | 231 | float tAvg; |
LievenHollevoet | 0:9a93fff79b27 | 232 | char command[32]; |
LievenHollevoet | 0:9a93fff79b27 | 233 | |
LievenHollevoet | 0:9a93fff79b27 | 234 | VCNL4010.ReadAmbiOnDemand (&ambiValue); // read ambi value on demand |
LievenHollevoet | 0:9a93fff79b27 | 235 | tAvg = sensor.GetAverageTemp(); |
LievenHollevoet | 0:9a93fff79b27 | 236 | tAvgByte = (int8_t)tAvg; |
LievenHollevoet | 0:9a93fff79b27 | 237 | ambiValueShort = (uint16_t)ambiValue; |
LievenHollevoet | 0:9a93fff79b27 | 238 | |
LievenHollevoet | 0:9a93fff79b27 | 239 | sprintf(command, "AT$SF=%04X%02X,2,0\n", ambiValueShort, tAvgByte); |
LievenHollevoet | 0:9a93fff79b27 | 240 | |
LievenHollevoet | 0:9a93fff79b27 | 241 | pc.printf("Sending ambient light level %i cts and temperature %i degrees C over Sigfox\n", ambiValueShort, tAvgByte); |
LievenHollevoet | 0:9a93fff79b27 | 242 | pc.printf("using modem command: %s", command); |
LievenHollevoet | 0:9a93fff79b27 | 243 | modem_command_check_ok(command); |
LievenHollevoet | 0:9a93fff79b27 | 244 | LED_1 = 1; |
LievenHollevoet | 0:9a93fff79b27 | 245 | } |
LievenHollevoet | 0:9a93fff79b27 | 246 | |
LievenHollevoet | 0:9a93fff79b27 | 247 | void senseTemperature() { |
LievenHollevoet | 0:9a93fff79b27 | 248 | float vOut = sensor.Sense(); |
LievenHollevoet | 0:9a93fff79b27 | 249 | //pc.printf("\n\rMCP9700 reading: Vout: %.2f mV", vOut); |
LievenHollevoet | 0:9a93fff79b27 | 250 | } |