Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf ·...

74
Självständigt arbete på grundnivå Independent degree project - first cycle Datateknik Computer Engineering Remote measuring and logging Evaluation of the Quectel OpenCPU technology Simon Nilsson

Transcript of Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf ·...

Page 1: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Självständigt arbete på grundnivåIndependent degree project - first cycle

DatateknikComputer Engineering

Remote measuring and loggingEvaluation of the Quectel OpenCPU technology

Simon Nilsson

Page 2: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

MID SWEDEN UNIVERSITYDepartment of Computer and System Science (DSV)

Examiner: Ulf Jennehag, [email protected]: Börje Hansson, [email protected]: Simon Nilsson, [email protected] programme: Programvaruteknik, 180 creditsMain field of study: Computer EngineeringSemester, year: Spring, 2015

ii

Page 3: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

AbstractThe company Sensefarm develops in the field of precision agriculture, more specif-ically a product for measuring and logging information on local environmentalconditions. The collected data is transmitted to a remote server using GSM tech-nology. They are looking into ways to improve their product. The purpose ofthis project is to evaluate the M66 GSM module and the accompanied OpenCPUtechnology. In the current product the GSM module is only used for the com-munication with the server. All other processing is done by a dedicated proces-sor. The OpenCPU technology allows for running customized firmware on theGSM module, possibly allowing it to take over the responsibilities of the dedi-cated processor. An application implementing all the necessary functionality wasdeveloped to test this capability. The finished application was able to fulfill allthe requirements specified, although it was not able to be tested in the field.

Keywords: Precision agriculture, GSM, OpenCPU, C, Embedded system, Sen-sors

iii

Page 4: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

AcknowledgementsI want to give my thanks to the people at Sensefarm for giving me the opportunityto do my thesis work there. Special thanks to Sensefarms founder/CTO AndersHedberg for taking time in his busy schedule to provide guidance.

I also want to thank Jonathan Bjarnason who also did his thesis at Sensefarm forproviding support when things did not go my way.

iv

Page 5: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

Table of Contents

Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii

Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . iv

Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1 Background and problem motivation . . . . . . . . . . . . . . . 11.2 Overall aim . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.3 Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.4 Detailed problem statement . . . . . . . . . . . . . . . . . . . . 21.5 Outline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 The OpenCPU Platform . . . . . . . . . . . . . . . . . . . . . . 42.1 Application Programming Interfaces . . . . . . . . . . . . . . . 42.1.1 System API . . . . . . . . . . . . . . . . . . . . . . . . . . . 42.1.2 Time API . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42.1.3 Timer API . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.1.4 Power Management API . . . . . . . . . . . . . . . . . . . . 52.1.5 Memory API . . . . . . . . . . . . . . . . . . . . . . . . . . 52.1.6 File System API . . . . . . . . . . . . . . . . . . . . . . . . 52.1.7 Hardware Interface API . . . . . . . . . . . . . . . . . . . . 52.1.8 GPRS API . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.1.9 Socket API . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.1.10 Watchdog API . . . . . . . . . . . . . . . . . . . . . . . . . 62.1.11 FOTA API . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.1.12 Debug API . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.1.13 RIL API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.2 Example Application . . . . . . . . . . . . . . . . . . . . . . . 72.2.1 Compiling . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.2.2 Downloading to module . . . . . . . . . . . . . . . . . . . . 92.2.3 Running . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3 Methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.1 Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

v

Page 6: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

3.2 Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.3 Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

4 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . 124.1 State management . . . . . . . . . . . . . . . . . . . . . . . . . 124.2 IMEI and Battery voltage . . . . . . . . . . . . . . . . . . . . . 124.3 Sensors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134.4 Global Positioning System . . . . . . . . . . . . . . . . . . . . 134.5 Data transmission . . . . . . . . . . . . . . . . . . . . . . . . . 144.6 Firmware Over-The-Air . . . . . . . . . . . . . . . . . . . . . . 164.7 Power Management . . . . . . . . . . . . . . . . . . . . . . . . 16

5 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185.1 Requirements met . . . . . . . . . . . . . . . . . . . . . . . . . 185.2 Requirements partially met . . . . . . . . . . . . . . . . . . . . 19

6 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206.1 Challenges during development . . . . . . . . . . . . . . . . . . 206.2 Unfinished SDK . . . . . . . . . . . . . . . . . . . . . . . . . . 206.3 Ethical aspects . . . . . . . . . . . . . . . . . . . . . . . . . . . 206.4 Future work . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Appendix A: Source code . . . . . . . . . . . . . . . . . . . . . . . . . 24

vi

Page 7: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

TerminologyADC Analog to Digital Converter. 6

API Application Programming Interface. 4, 7, 10, 12, 18, 19

EINT External Interrupt. 6

FOTA Firmware Over-The-Air. 3, 7, 16–18

FTP File Transfer Protocol. 16

GCC GNU Compiler Collection. 10

GPIO General-Purpose Input/Output. 5

GPRS General Packet Radio Service. 6, 17

GPS Global Positioning System. 3, 12–14, 17, 18

GSM Global System for Mobile communications. 1, 4, 7, 16

HTTP HyperText Transfer Protocol. 12, 14–18

I/O Input/Output. 1, 5

I2C Inter-Integrated Circuit. 3, 6, 13, 17, 18, 20

IDE Integrated Development Environment. 10

IMEI International Mobile station Equipment Identity. 12, 17

JSON JavaScript Object Notation. 12, 14–18

NMEA National Marine Electronics Association. 14

PWM Pulse-Width Modulation. 6

RAM Random Access Memory. 5

REST Representational State Transfer. 14

vii

Page 8: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

RIL Radio Interface Layer. 7

RTC Real Time Clock. 4, 16, 18

SDK Software Development Kit. 4, 9–11, 16, 20

SPI Serial Peripheral Interface. 6

TCP Transmission Control Protocol. 6, 20

UART Universal Asynchronous Receiver/Transmitter. 5, 11

UDP User Datagram Protocol. 6

UFS User File System. 5

URL Uniform Resource Locator. 14, 16

USB Universal Serial Bus. 9

viii

Page 9: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

1 IntroductionSensefarm AB [1] is a small but ambitious company based in Lund, Sweden.They develop solutions for remotely measuring and logging information on localenvironmental conditions. Their products are primarily made for the agriculturalsector but have also been adopted by for example a golf course and Malmö Mu-nicipality.

The company’s product consists of a base station and a variable amount of con-nected sensors. The base stations come in two forms, one that is placed underground and is completely reliant on the included battery, and one that is mountedabove ground with a solar cell.

The conditions that can be measured include temperature, humidity, soil mois-ture, precipitation and location. The base stations transmit collected data to aserver using GSM-technology where GSM stands for ”Global System for Mobilecommunications”, the same technology that is used in mobile phones.

The data is presented to the user via a web-interface that can be accessed usinga computer or mobile device. The end user can use this information in order toestimate for example, when the next irrigation should be done based on the soilmoisture.

1.1 Background and problem motivationThe current solution used in the base stations has an Arduino-processor that takescare of I/O-operations (Input/Output) and processing. The Arduino communi-cates with a separate GSM-module in order to transmit the data to the server.

The company feels the need to make their product more affordable and want toknow if it is possible to combine the functionality of the Arduino-processor andthe GSM-module. The GSM-module currently in use is the M10-module devel-oped by a company called Quectel. This module is not programmable and cantherefor not fulfil this task.

The M66-module [2] is another GSM-module also made by Quectel. The phys-ical module as seen in Figure 1.1 measures at only 15.8 × 17.7 × 2.3 millime-ters. The special thing about this module is that it contains a technology calledOpenCPU [3], this technology allows for the programming of custom firmwarefor the module, possibly allowing it to take over the Arduino-processor’s respon-sibilities.

1

Page 10: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

Figure 1.1: The M66 module. [2]

1.2 Overall aimThe project’s overall aim is to investigate if it is possible for the M66 module incombination with the OpenCPU technology to replace the current solution. Inorder to accomplish this goal, a software application equivalent to the Arduinocounterpart will be developed. The application should preferably work for bothproduct types, the base units with or without solar cells, without any modificationto the code.

If successful the Arduino will become redundant and can be excluded entirely.The result will be a smaller, cheaper and more energy efficient solution. Energyefficiency is especially important to improve the product’s battery life.

1.3 ScopeThe scope of this thesis is limited to the process of developing the firmware andtesting it using a provided evaluation kit that has all the necessary hardware. Thehardware itself will not be covered in-depth.

1.4 Detailed problem statementIn order for the M66 module to work as a replacement the following criteria mustbe met:

1. Be able to run on a battery for up to three years without human intervention.

2

Page 11: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

2. Be able to communicate with and read information from I2C-devices.

3. Be able to read positioning data from an external GPS-device.

4. Be able to transmit data to the company’s servers and receive a response.

5. Be able to receive updates using Firmware Over-The-Air (FOTA).

6. Be able to power off and wake up at a set time.

If these criteria can be met the M66 module and the OpenCPU platform can beconsidered an acceptable replacement for the existing solution.

1.5 OutlineChapter 2 describes the OpenCPU platform and what is needed to get started de-veloping with it. Chapter 3 describes the method used for developing the appli-cation. Chapter 4 describes how each major feature of the application was imple-mented. Chapter 5 summarizes the result of the project and compares the result tothe requirement specification. Chapter 6 contains an analysis of the result.

3

Page 12: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

2 The OpenCPU PlatformOpenCPU is what Quectel choose to call their solution that lets the developerupload a custom application to some of their GSM-modules. This is not to beconfused with the system for embedded scientific computing and reproducible re-search also called OpenCPU [4] which is a completely separate technology.

Quectel supplies a user guide for how to use theOpenCPUplatform [5]. OpenCPUapplications are written using the C programming language. When developing inC one might be used to taking advantage of the standard C libraries like stdio.hand stdlib.h, these are not available here and the programmer is instead limitedto the supplied library functions of the SDK. Variants of common functions likeatoi() and sprintf() are available trough the ql_stdlib.h header.

2.1 Application Programming InterfacesA set of Application Programming Interface (API) functions are included with theSDK. These functions give the developer access to things like hardware interfaces,connection management, a file system, power management, and more. The API:sare separated into multiple categories described below.

2.1.1 System APIHeader file: ql_system.h

Contains system-related functionality to get system information and multitaskingutilities like mutex and semaphores. Also has the essential functionality requiredto set up the required message loop.

2.1.2 Time APIHeader file: ql_time.h

Functions to get and set the time of the built in Real Time Clock (RTC). The RTCkeeps track of the time even when the module is turned off and draws a very lowamount of power.

4

Page 13: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

2.1.3 Timer APIHeader file: ql_timer.h

Gives access to timer functionality. There are 2 different kinds of timers available,a common timer and a fast timer. Only one fast timer can be used at a time whileyou can have 10 common timers simultaneously. The fast timer has the advantageof better accuracy.

2.1.4 Power Management APIHeader file: ql_power.h

Functions for powering off the module and enabling a low power mode (SleepMode). Also allows for customization of the PWRKEY input pin.

2.1.5 Memory APIHeader file: ql_memory.h

Allows for dynamic memory management. Has a function for allocating memoryand one for freeing memory.

2.1.6 File System APIHeader file: ql_fs.h

Gives access to a User File System (UFS) in the flash storage or ability to storefiles directly in RandomAccessMemory (RAM). Functions exists for writing andreading files and directories.

2.1.7 Hardware Interface APIHeader file: ql_uart.h

Universal Asynchronous Receiver/Transmitter (UART) allows for communica-tion using one of the three available UART-ports.

Header file: ql_gpio.h

General-Purpose Input/Output (GPIO) allows for individual control of the avail-able I/O-pins.

Header file: ql_eint.h

5

Page 14: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

External Interrupt (EINT) allows for registration of interrupt handlers for 2 pinswith interrupt support.

Header file: ql_pwm.h

Pulse-WidthModulation (PWM) allows for PWM-output on one of the pins.

Header file: ql_adc.h

Analog to Digital Converter (ADC) allows measuring external voltage on a pinin the range 02̃800mV.

Header file: ql_iic.h

Inter-IntegratedCircuit (I2C) allows for communication using the I2Cprotocol.

Header file: ql_spi.h

Serial Peripheral Interface (SPI) allows for communication using the SPI proto-col.

2.1.8 GPRS APIHeader file: ql_gprs.h

Functionality for enabling and configuring the GPRS.

2.1.9 Socket APIHeader file: ql_socket.h

Support for creating sockets for User Datagram Protocol (UDP) or TransmissionControl Protocol (TCP) communication over GPRS.

2.1.10 Watchdog APIHeader file: ql_wtd.h

For working with an external watchdog timer. Watchdog timers are used to detectand recover from malfunctions in hardware or software.

2.1.11 FOTA APIHeader file: ql_fota.h

6

Page 15: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

Functionality for Firmware Over-The-Air (FOTA) updates.

2.1.12 Debug APIHeader file: ql_trace.h

Only has one simple function for outputting text to the second (DEBUG) serialport.

2.1.13 RIL APIHeader file: ril.h

Radio Interface Layer (RIL) gives access to the GSM functionality of the mod-ule. A lot of the functionality is wrapped in API functions, other features canbe accessed with AT commands. Using AT commands is the traditional way tocommunicate with a GSM module when using an external processor, in that casethe commands are transmitted using the serial interface. Using the RIL API, ATcommands can be sent in code using a function call.

Header files: ril_telephony.h, ril_sms.h, ril_network.h, ril_location.h, ril_system.h

These headers contain wrapper functions around AT commands for their respec-tive areas.

2.2 Example ApplicationFigure 2.1 shows the least code needed for anOpenCPU application. The proc_main_task()method is equivalent to the main method in a C application. The application needsto read messages from the message queue. If the messages are not read the queuewill fill up and eventually crash the application.

7

Page 16: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

#include "ql_type.h"#include "ql_system.h"#include "ql_trace.h"

/*** Application main method.*/

void proc_main_task(s32 taskId){

// Print a message to see that the application works.Ql_Debug_Trace("Hello World!\r\n");

ST_MSG msg;

// Message loopwhile(TRUE){

// Blocks until a message is available in queue.Ql_OS_GetMessage(&msg);

switch(msg.message){

// Handle any messages relevant to application.

default:break;

}}

}

Figure 2.1: A simple OpenCPU application example.

Messages are read using the Ql_OS_GetMessage() function with a pointer to aST_MSG structure as a parameter. The definition of ST_MSG can be seen inFigure 2.2. u32 is an unsigned 32-bit integer.

typedef struct {u32 message;u32 param1;u32 param2;u32 srcTaskId;

} ST_MSG;

Figure 2.2: The definition of ST_MSG struct.

Messages can be sent by the module to describe its state but customized messagescan also be sent by the application itself.

8

Page 17: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

2.2.1 CompilingThe SDK comes with a preconfigured makefile and a Windows Batch file. Bycalling the Batch file with the commands ”make clean” and ”make new” a newbinary file will be produced in the build directory.

2.2.2 Downloading to moduleWhen the application has been compiled into a binary file it is ready to be down-loaded onto the module. This is done using the software called QFlash suppliedby Quectel. A converter cable between Universal Serial Bus (USB) and RS-232 isused to connect to the module. RS-232 is the standard for serial communication.In order to start the download, the following process should be followed:

1. Connect the cable between the MAIN UART port of the evaluation boardand a free USB port on your computer.

2. Start QFlash and select the correct serial port.

3. Press ”Browse” and select the configuration file that was generated alongwith the binary file when compiling.

4. Press ”Start” in QFlash.

5. Supply power to the evaluation board and put the D/L switch in the ONstate.

The download process should now start. The time to complete depends on thesize of the application. When the process has finished the module can be turnedoff and the QFlash application can be closed.

2.2.3 RunningAfter the application has been downloaded to the module it is ready for testing.Supply the module with power, hold the power button pressed down for two sec-onds, then the module will start. In the case of the example application in Section2.2 the output trough the DEBUG UART port should be as in Figure 2.3.

OpenCPU_GS3_SDK_V1.2Hello World!

Figure 2.3: Serial output from example application.

9

Page 18: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

3 MethodologyThis chapter describes themethodology usedwhen implementing the project.

3.1 DocumentationDocumentation for the M66 module supplied by Quectel will be studied. Morespecifically the OpenCPU platform and the accompanied API. Documentationcomes in form of PDF-files.

3.2 DevelopmentDevelopment is done according to the principles of agile development with focuson implementing one feature at a time. Short meetings are held each morning atthe company where the current progress and upcoming steps are discussed.

When all features have been implemented individually they will be combined toform a working implementation to be used as a proof of concept.

Version control with git is used in the form of a private repository on GitHub [6].This gives several benefits. In addition to the obvious benefits such as keepingtrack of the code and allowing rollbacks, it also encourages working on one partat a time in order to make meaningful commits.

3.3 ToolsThe Software Development Kit (SDK) supplied by Quectel for the OpenCPUplatform only supports Windows operating systems. Windows 7 will be usedas operating system. The SDK comes in two variations, one with the EclipseIntegrated Development Environment (IDE) and a command-line version withoutany IDE.

The command-line version will be used because it allows for full control and it isnot dependant on the editor used. The programming language is C in combinationwith a GCC compiler. The application gets compiled into a .bin file. This filecan be uploaded to the M66 module using a tool called QFlash also supplied byQuectel.

The editor used to write the code is Atom, ”A hackable text editor for the 21st

10

Page 19: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

Figure 3.1: The M10 evaluation board used to develop for the M66 module. [8]

Century” [7]. This is a text editor that can be extended trough a wide range ofpackages.

The only way to debug the application once uploaded to the module is trough oneof the three on-board UART ports. UART stands for Universal AsynchronousReceiver/Transmitter, and is a standard for serial communication, a common wayto communicate by sending characters between two devices. Although any soft-ware capable of serial communication should work, an application called QCOMfrom Quectel will be used as it is a part of the SDK.

The evaluation kit supplied by Quectel has all the necessary hardware requiredto develop and test applications on the M66 module. The board seen in Figure3.1 is the main part of the kit. It gives access to all the inputs and outputs ofthe module and has some on-board hardware for simple connection of power andserial communication. This evaluation board can be used for several differentmodules. In Figure 3.1 a M10 module is mounted on the board.

11

Page 20: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

4 ImplementationThis chapter goes trough each part of the implementation. Figure 4.4 shows aflowchart of the application to be implemented.

As C is a procedural language and does not support classes or namespaces, anaming convention was adopted to separate parts of the application. For examplethe function to initiate GPS input is named Sf_GPS_Init(), Sf is the applicationwide ”namespace” and GPS means it is a part of the GPS implementation.

The API works as an abstraction layer against the module’s hardware. The realwork consists of implementing the collection of data (battery status, IMEI, sen-sors, GPS), formatting the data so it can be sent over the network (JSON), sendingand receiving HTTP-messages, and power management. In addition to this it isvery important that the application is stable and prepared for any conditions thatmight cause malfunction.

The complete source code can be viewed in Appendix A.

4.1 State managementBecause the application must constantly listen for new messages in the messageloop, only short operations can be reasonably executed in synchronous fashion.Longer operations like data transmission and serial communication is done asyn-chronously using callbacks. The application needs to keep track of both the stateof the module and the state of the application itself. To comply with these require-ments some kind of state management is needed.

It made sense to use the API’s built in support for sending customized messages.This way all logic can be run from the message loop. After an operation is com-pleted the application sends a message to itself containing the new state and thenreturns control to the message loop.

4.2 IMEI and Battery voltageInternational Mobile station Equipment Identity (IMEI) [9] is a 15 digit string thatcan be used to uniquely identify a mobile device. In the case of this applicationthe IMEI is sent along with every request to the server to let the server knowwhich unit is sending the data. No API function is provided to read the IMEI ofthe module. An AT Command is however available ”AT+GSN”, this command

12

Page 21: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

returns the IMEI as a string.

The current battery voltage is also sent along with requests to the server. This al-lows the user to see the status of the battery and determine if it requires a recharge.An API function is available to get the battery status RIL_GetPowerSupply(), thisfunction did not work as expected and returned an incorrect value, an underly-ing AT command had to be used here also. In this case it was the ”AT+CBC”command.

4.3 SensorsTo communicate with the sensor Inter-Integrated Circuit (I2C) is used [11]. I2Cis a protocol primarily used to communicate between circuits on the same board,but also works for shorter distances using wires. It uses two bidirectional lines,DCA (data) and SCL (clock signal). Even if many other types of sensors have theI2C-protocol in common, they all use different message protocols and thereforerequire specific code implementations.

Support for one type of sensor was implemented. Although the product is meantto work with multiple sensors, implementing one is enough to evaluate the plat-form. The SHT2x [10] is a series of sensors for measuring temperature and rel-ative humidity. The series has 3 different models with varying accuracy. Themiddle variant called SHT21 is used for this implementation. However, sincethe message protocol of the sensors in the series are identical, they should all becompatible.

The I2C-protocol defines two types of devices, ”master” and ”slave”. The SHT2xcan only act as a slave and the module thus takes the role of master. The masterdevice generates the clock signal and initiates communication with a slave deviceby its address. The address is a 7-bit integer value, in the case of SHT2x theaddress is the decimal value 80. By sending various commands it is possible toread the sensor’s unique id, the measured temperature, and the measured relativehumidity.

There is much more to the I2C protocol which will not be explained here as it isnot the subject of this thesis.

4.4 Global Positioning SystemGlobal Positioning System (GPS) should be familiar to most people as it is a tech-nology used frequently in today’s society. It is essentially a system that determinesthe current position by using satellites. The application should be able to read lo-cation data from an external GPS device that is connected to the auxiliary UART-

13

Page 22: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

port. The GPS device used in this implementation is called FGPMMOPA6H andis made by GlobalTop Technology. This device outputs data in National MarineElectronics Association (NMEA)-format [12].

The NMEA standard defines several different message strings, called sentences[13]. Each sentence contains different values and not all sentences are supportedby every device. This implementation only parses data from the $GPGGA and$GPRMC sentences from the GPS device.

Longitude, latitude and altitude is read from $GPGGA. Speed and course is readfrom $GPRMC.

4.5 Data transmissionIn order to upload gathered data the module needs to communicate with Sense-farms server. The server is running what is known as a Representational StateTransfer (REST) service [14] using HyperText Transfer Protocol (HTTP) [15]and the JavaScript Object Notation (JSON) format [16].

To implement HTTP the Socket API was used to to create a TCP connection to theserver. The protocol is fairly simple to implement. The client (module) sends arequest to the server and the server sends a response back through the connection.The messages follow a certain format, starting with headers followed by optionalcontent. The header and content is separated with a double newline. Figure 4.1shows how the HTTP message might look including the JSON data.

We can see that the request is of type PUT and the target Uniform Resource Lo-cator (URL) is in.example.com/test. Spacing and newline-characters are addedin theJSON data for clarity, but are not included when sent from the application.This is to make the message as small as possible. The datastreams array containsone entry for the battery voltage, a temperature reading from a sht2x sensor, anda relative humidity reading from the same sensor.

14

Page 23: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

PUT /test HTTP/1.1Host: in.example.comContent-Length: 247Content-Type: application/jsonConnection: close

{"version": "1.2.2","IMEI": "863071010199115","datastreams": [

{"id": "Power","val": "4.18"

},{

"id": "008016B14598010 -t","val": "17.0"

},{

"id": "008016B14598010 -r","val": "40.4"

}]

}

Figure 4.1: HTTP message example.

The response from the server seen in Figure 4.2 also contains JSON. This responseonly has a number called s with a value of 3600, which tells the module that thenext transmission should be made after 3600 seconds (or 1 hour). This value canbe changed via the web-interface.

Connection: closeContent-Type: application/jsonDate: Fri, 22 May 2015 12:32:46 GMTServer: nginx

{"s": 3600

}

Figure 4.2: HTTP response from server.

15

Page 24: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

4.6 Firmware Over-The-AirThe module has built in support for updating the firmware over-the-air. By usingthe code included with the SDK it is accomplished simply by calling a functionwith the URL to a binary file on either a HTTP-server or a File Transfer Protocol(FTP)-server [17]. The module will then download the binary file and install it.When the operation is completed the module will restart and boot up using thenew firmware.

As Sensefarm’s current product does not support FOTA there is no existing im-plementation on the server side. It could be implemented by adding a field to theJSON-response as seen in Figure 4.3.

{"s": 3600,"update": "http://download.example.com/update.bin"

}

Figure 4.3: Proposal for message format when updating firmware.

4.7 Power ManagementIn order to conserve battery the module needs to completely power off betweenmeasurements. By using the built in Real Time Clock (RTC) an alarm can be setto power on the module at a certain time. When the RTC alarm fires, the module ispowered on in a limitedmode called ”ALARMMODE”. This mode disables mostof the module’s functionality. In order to use GSM functionality the applicationcan switch to a full functionality mode.

16

Page 25: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

Power On

Has fullfunctionality?

Enable fullfunctionality

No

Read batteryvoltage

Yes

Enough batteryto continue? Power off

No

Read IMEI

Yes

Read sensorvalues (I2C) Read GPS Construct

JSON Wait for GPRS

Send HTTPrequest

Receiveresponse

FOTA updateavailable?

Set poweron alarm

NoPower off

Wait for alarm

Updatefirmware

Yes

Reboot

Figure 4.4: Application flowchart

17

Page 26: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

5 ResultsOut of the six points in the requirement specification, five were fully met and onepartially met. Based on these results the M66-module and the OpenCPU platformis a viable replacement for the existing solution.

5.1 Requirements metThe following list shows the requirements that were successfully implemented.

• Application can communicate with and read information from I2C-devices.

By using the Hardware Interface API in combinationwith a code implemen-tation to communicate with the SHT2x sensor this requirement was met.

• Application can read positioning data from an external GPS-device.

The application was able to read data from the GPS device using the aux-iliary serial port of the module. This data was successfully parsed in orderto produce longitude, latitude, altitude, speed and course values.

• Application can transmit data to the company’s servers and receive aresponse.

By using the Socket API in combination with code implementations forHTTP and JSON this requirement was met.

• Application can receive updates using FirmwareOver-The-Air (FOTA).

The module has built in support for FOTA. The implementation checks theJSON in the server response for the presence of the ”update” field, if thefield exists a function is called in the modules API in order to start the up-date.

• Application can power off and wake up at a set time.

The wake up functionality was accomplished by setting an alarm in themodules RTC. Powering of the module is as simple as calling a function in

18

Page 27: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

the API.

5.2 Requirements partially metThe following list shows the requirement that was not fully met.

• Be able to run on a battery for up to three years without human inter-vention.

This requirement is met in a theoretical sense but time constraints do notallow for the possibility to test this in practical use.

19

Page 28: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

6 ConclusionsBased on the results of developing using the evaluation kit, I would say that theM66 module and the OpenCPU platform would work very well as a replacementfor the current solution.

In order to fully evaluate the advantages of using this new solution a prototypewould have to be made using components similar to that used in finished product.This would allow comparisons to be made of power usage, production cost, andphysical size of the finished product.

6.1 Challenges during developmentOne of the major challenges during development was debugging. When some-thing went wrong leading to a crash, the module just started writing a long stringof incomprehensible characters to the debug serial output. Without any error mes-sages to rely on, the most effective way to find problems was to place as manydebug traces as possible to find the place where the error occurred.

The lack of better debugging support was most noticeable when I was trying todownload a larger file using a TCP-socket. Because the code used a busy-waitingloop, the message queue overflowed which resulted in a crash. This took a verylong time to figure out as the crash could happen at different times depending onhow fast the file was downloading.

6.2 Unfinished SDKThe OpenCPU platform is still relatively new and Quectel is still developing theSDK. This was made evident when I was unable to get either the I2C-functionalityor floating point variables to work at all, until a technician from Quectel suppliedme with a newer unreleased version of the SDK.

6.3 Ethical aspectsIf the solution evaluated in this work is to be implemented in real use it would leadto a product with less components, thus minimizing the environmental impact.The product would also be made more cost effective, allowing wider utilization.A wider utilization of the product would mean that waste of resources could beavoided on a larger scale. By waste of resources I mean things like irrigating

20

Page 29: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

when it is not really needed. This is important because the worlds population isgrowing meaning there are more and more people in need of food. Farms need tobe made as efficient as possible to account for this.

The data sent between the module and server is not encrypted or protected by anysecurity measures beyond those implemented by the network operator, and is thussusceptible to unauthorized access. The data in this case may not be consideredvery sensitive, but things like location data might not be something you wantoutsiders to get access to.

6.4 Future workFuture work may involve implementing security measures. There is also the pos-sibility to make use of the module’s file-system for intermediate storage to enablefrequent logging with occasional transmissions.

21

Page 30: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

References[1] Sensefarm,

http://www.sensefarm.com/Retrieved 2015-05-04.

[2] Quectel Wireless Solutions, ”GSM/GPRS M66”,http://www.quectel.com/product/prodetail.aspx?id=73Retrieved 2015-05-04.

[3] Quectel Wireless Solutions, ”OpenCPU”,http://www.quectel.com/technology/detail.aspx?id=3Retrieved 2015-05-04.

[4] OpenCPU, ”An API for Embedded Scientific Computing”,https://www.opencpu.org/Retrieved 2015-05-06.

[5] Quectel wireless Solutions, ”M66-OpenCPU User Guide”,http://www.quectel.com/qdownload/M66_OpenCPU_SDK.htmlDate 2014-10-14, Retrieved 2015-05-21.

[6] GitHub,https://github.com/Retrieved 2015-05-21.

[7] Atom,https://atom.io/Retrieved 2015-05-04.

[8] Quectel Wireless Solutions, ”EVB Toolkits”,http://www.quectel.com/product/prolist.aspx?classid=288230376151711744Retrieved 2015-05-20.

[9] Wikipedia, ”International Mobile Station Equipment Identity”,http://en.wikipedia.org/wiki/International_Mobile_Station_Equipment_IdentityPublished 2015-05-15. Retrieved 2015-05-21.

[10] Sensiron, ”SHT2x - Digital Humidity & Temperature Sensor”,http://www.sensirion.com/en/products/humidity-temperature/humidity-temperature-sensor-sht2x/Retrieved 2015-05-21.

[11] Wikipedia, I2C,

22

Page 31: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

http://en.wikipedia.org/wiki/I2CPublished 2015-05-20. Retrieved 2015-05-21.

[12] Wikipedia, ”NMEA 0183”,http://en.wikipedia.org/wiki/NMEA_0183Published 2015-05-16. Retrieved 2015-05-21.

[13] Glenn Baddeley, ”GPS - NMEA sentence information”,http://aprs.gids.nl/nmea/Published 2001-07-20. Retrieved 2015-05-21.

[14] Wikipedia, ”Representational state transfer”,http://en.wikipedia.org/wiki/Representational_state_transferPublished 2015-05-20. Retrieved 2015-05-21.

[15] Wikipedia, ”Hypertext Transfer Protocol”,http://en.wikipedia.org/wiki/Hypertext_Transfer_ProtocolPublished 2015-05-17. Retrieved 2015-05-21.

[16] JSON, ”Introducing JSON”,http://json.org/Retrieved 2015-05-21.

[17] Wikipedia, ”File Transfer Protocol”,http://en.wikipedia.org/wiki/File_Transfer_ProtocolPublished 2015-05-22. Retrieved 2015-05-22.

23

Page 32: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

Appendix A: Source codeThe file config.h is not included as it contains company sensitive information.

main.c1 /*2 * main.c3 *4 * Created on: 27 mar 20155 * Author: Simon Nilsson6 */7 #ifdef __CUSTOMER_CODE__89 #include "ql_common.h"10 #include "ql_system.h"11 #include "ql_type.h"12 #include "ql_trace.h"13 #include "ql_stdlib.h"14 #include "ql_uart.h"15 #include "ql_memory.h"16 #include "ql_error.h"17 #include "ql_power.h"18 #include "ql_gprs.h"19 #include "ql_fs.h"20 #include "ql_socket.h"21 #include "fota_main.h"2223 #include "ril.h"24 #include "ril_util.h"25 #include "ril_system.h"26 #include "ril_network.h"2728 #include "sf_config.h"29 #include "sf_types.h"30 #include "sf_utility.h"31 #include "sf_iic.h"32 #include "sf_sht21.h"33 #include "sf_json.h"34 #include "sf_tcp.h"35 #include "sf_http.h"36 #include "sf_gps.h"3738 #define MSG_ID_SF_STATE (MSG_ID_USER_START + 100)3940 typedef enum41 {42 SF_STATE_STARTED ,43 SF_STATE_RIL_READY ,

24

Page 33: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

44 SF_STATE_FULL_FUNC ,45 SF_STATE_GPRS_READY ,46 SF_STATE_DATA_READY ,47 SF_STATE_DATA_SENT ,48 SF_STATE_DATA_RECEIVED ,49 SF_STATE_UPGRADE ,50 SF_STATE_FINISHED ,51 SF_STATE_FAILURE52 } Enum_Sf_State;5354 char data[512];55 char response[515];5657 s32 dataLength;58 s32 sent, received;5960 // Forward declarations61 // -------------------------------------62 static void setState(Enum_Sf_State state);63 static void prepareData(void);64 static void sendData(void);65 static void handleResponse(void);66 static void upgrade(const char* url);67 static void failure(void);68 static void finish(void);6970 void send_callback(s32 error);71 void receive_callback(s32 error);72 // -------------------------------------7374 static void setState(Enum_Sf_State state)75 {76 Ql_Debug_Trace("<-- setState %d -->\r\n", state);77 Ql_OS_SendMessage(0, MSG_ID_SF_STATE , state, 0);78 }7980 static void prepareData(void)81 {82 Ql_Debug_Trace("<-- Preparing data -->\r\n");8384 ST_SENSOR datastreams[20];85 u8 streamCount = 0;8687 // Add battery voltage as a datastream88 // Power: <voltage>89 Ql_Debug_Trace("<-- Reading battery voltage -->\r\n");90 float voltage;91 if(Sf_GetBatteryVoltage(&voltage))92 {93 Ql_Debug_Trace("Battery voltage: %fV\r\n", voltage);9495 if(voltage < SF_LOW_VOLTAGE_LIMIT)

25

Page 34: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

96 {97 Ql_Debug_Trace("Low voltage, powering down!\r\n");98 setState(SF_STATE_FAILURE);99 return;100 }101102 // Set id103 Ql_strcpy(datastreams[streamCount].id, "Power");104105 // Set value106 datastreams[streamCount].value = voltage;107108 ++streamCount;109 }110 else return setState(SF_STATE_FAILURE);111112 // Read IMEI number.113 Ql_Debug_Trace("<-- Fetching IMEI -->\r\n");114 char imei[16];115 if(Sf_GetIMEI(imei))116 Ql_Debug_Trace("IMEI: %s\r\n", imei);117 else118 return setState(SF_STATE_FAILURE);119120 // Check IIC devices121 Ql_Debug_Trace("<-- Checking IIC-devices -->\r\n");122 if(Sf_IIC_Init())123 {124 // Check for SHT21125 Sf_SHT21_Read(datastreams , &streamCount);126127 // Uninitialize IIC128 Sf_IIC_Uninit();129 }130131 // GPS132 Sf_GPS_Read(datastreams , &streamCount);133 Sf_GPS_Uninit();134135 // Construct JSON136 Ql_Debug_Trace("<-- Building JSON -->\r\n");137 dataLength = Sf_JSON_Build(data, imei, datastreams ,

streamCount);138139 Ql_Debug_Trace("%s\r\n", data);140141 setState(SF_STATE_DATA_READY);142 }143144 static void sendData(void)145 {146 Ql_Debug_Trace("<-- Sending data -->\r\n");

26

Page 35: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

147148 sent = 0;149 received = 0;150151 // Activate GPRS152 if(!Sf_ActivateGPRS())153 {154 Ql_Debug_Trace("Failed to activate GPRS!\r\n");155 setState(SF_STATE_FAILURE);156 return;157 }158159 if(!Sf_HTTP_SendRequest(SF_HTTP_SERVER , SF_REQUEST_TYPE ,

dataLength , send_callback))160 {161 Ql_Debug_Trace("Failed to send request!\r\n");162 setState(SF_STATE_FAILURE);163 return;164 }165 }166167 static void handleResponse(void)168 {169 Sf_DeactivateGPRS();170171 Ql_Debug_Trace("<-- Handle response -->\r\n");172 Ql_Debug_Trace("%s\r\n", response);173174 char update[256];175 s32 s, log;176177 // Parse JSON178 Sf_JSON_Parse(response , &s, &log, update);179180 Ql_Debug_Trace("s: %d\r\n", s);181 Ql_Debug_Trace("log: %d\r\n", log);182 Ql_Debug_Trace("update: %s\r\n", update);183184 if(Ql_strlen(update) > 0)185 {186 setState(SF_STATE_UPGRADE);187 upgrade(update);188 return;189 }190191 // Set wake up timer.192 if(s)193 {194 Sf_SetWakeupDelay(s);195 setState(SF_STATE_FINISHED);196 }197 else

27

Page 36: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

198 setState(SF_STATE_FAILURE);199 }200201 static void upgrade(const char* url)202 {203 Ql_Debug_Trace("<-- UPGRADING -->\r\n");204205 ST_GprsConfig config = { SF_APN, "", "", 0, NULL, NULL };206 s32 err = Ql_FOTA_StartUpgrade((u8*)url, &config, NULL);207 if(err)208 {209 Ql_Debug_Trace("FOTA update failed!\r\n");210 setState(SF_STATE_FAILURE);211 }212 }213214 static void failure()215 {216 Ql_Debug_Trace("<-- FAILURE -->\r\n");217218 // Retry later219 Sf_SetWakeupDelay(SF_RETRY_DELAY);220221 // Power down222 Ql_Debug_Trace("<-- Powering down -->\r\n");223 Ql_PowerDown(1);224 }225226 static void finish()227 {228 Ql_Debug_Trace("<-- FINISH -->\r\n");229230 // Show time spent231 u64 timeSincePwrOn = Ql_GetMsSincePwrOn();232 Ql_Debug_Trace("<-- Operation took: %dms -->\r\n", (u32)

timeSincePwrOn);233234 // Power down235 Ql_Debug_Trace("<-- Powering down -->\r\n");236 Ql_PowerDown(1);237 }238239 /**240 * Application Entry Point241 * @param taskId The task id.242 */243 void proc_main_task(s32 taskId)244 {245 Ql_Debug_Trace("Sensefarm Application 1.0\r\n");246 Ql_Debug_Trace("Made by: Simon Nilsson 2015\r\n");247248 Enum_Sf_State state = SF_STATE_STARTED;

28

Page 37: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

249250 // Start listening to GPS251 Sf_GPS_Init();252253 ST_MSG msg;254255 // Message loop256 while (TRUE)257 {258 Ql_OS_GetMessage(&msg);259260 if(msg.message == MSG_ID_SF_STATE)261 {262 state = msg.param1;263 switch (state)264 {265 case SF_STATE_FULL_FUNC:266 prepareData();267 break;268269 case SF_STATE_GPRS_READY:270 sendData();271 break;272273 case SF_STATE_DATA_SENT:274 Sf_HTTP_GetResponse(receive_callback);275 break;276277 case SF_STATE_DATA_RECEIVED:278 handleResponse();279 break;280281 case SF_STATE_FAILURE:282 failure();283 return;284285 case SF_STATE_FINISHED:286 finish();287 return;288289 default:290 break;291 }292 }293294 else if(msg.message == MSG_ID_RIL_READY)295 {296 Ql_Debug_Trace("<-- RIL is ready -->\r\n");297 Ql_RIL_Initialize();298299 Ql_Debug_Trace("<-- Synchronizing time -->\r\n");300 Sf_SyncTime();

29

Page 38: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

301302 setState(SF_STATE_RIL_READY);303 }304305 else if(msg.message == MSG_ID_URC_INDICATION)306 {307 switch (msg.param1)308 {309 case URC_CFUN_STATE_IND:310311 Ql_Debug_Trace("<-- CFUN Status:%d -->\r\n", msg.

param2);312313 // Minimum functionality (when started from ALARM)314 if(msg.param2 == 0)315 {316 Ql_Debug_Trace("<-- Enabling full functionality -->\

r\n");317 Sf_EnableFullFunctionality();318 }319320 setState(SF_STATE_FULL_FUNC);321 break;322323 case URC_SYS_INIT_STATE_IND:324325 Ql_Debug_Trace("<-- Sys Init Status %d -->\r\n", msg.

param2);326 break;327328 case URC_SIM_CARD_STATE_IND:329330 if (SIM_STAT_READY == msg.param2)331 {332 Ql_Debug_Trace("<-- SIM card is ready -->\r\n");333 }334 else335 {336 Ql_Debug_Trace("<-- SIM card is not available , cause

:%d -->\r\n", msg.param2);337 /* cause: 0 = SIM card not inserted338 * 2 = Need to input PIN code339 * 3 = Need to input PUK code340 * 9 = SIM card is not recognized341 */342 }343 break;344345 case URC_GSM_NW_STATE_IND:346 break;347348 case URC_GPRS_NW_STATE_IND:

30

Page 39: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

349350 if (NW_STAT_REGISTERED == msg.param2 || msg.param2 ==

NW_STAT_NOT_ACTIVE)351 {352 Ql_Debug_Trace("<-- GPRS ready -->\r\n");353354 if(state == SF_STATE_DATA_READY)355 setState(SF_STATE_GPRS_READY);356357 break;358 }359 else360 {361 Ql_Debug_Trace("<-- GPRS network status:%d -->\r\n",

msg.param2);362 /* status: 0 = Not registered , module not currently

search a new operator363 * 2 = Not registered , but module is

currently searching a new operator364 * 3 = Registration denied365 */366367 u32 rssi;368 u32 ber;369 RIL_NW_GetSignalQuality(&rssi, &ber);370 Ql_Debug_Trace("<-- Signal strength:%d, BER:%d -->\r

\n", rssi, ber);371 }372 break;373374 default:375 Ql_Debug_Trace("<-- Other URC: type=%d\r\n", msg.

param1);376 break;377 }378379 }380381 }382383 }384385 void send_callback(s32 error)386 {387 if(error)388 {389 Ql_Debug_Trace("Failed to send data! [%d]\r\n", error);390 Sf_DeactivateGPRS();391 return;392 }393394 // Send header

31

Page 40: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

395 while(sent < dataLength)396 {397 s32 ret = Sf_TCP_Send((u8*)data + sent, dataLength - sent);398399 // Blocking400 if(ret == SOC_WOULDBLOCK)401 return;402403 // Error404 else if(ret < 0)405 {406 Ql_Debug_Trace("Failed to send data! [%d]\r\n", ret);407 Sf_DeactivateGPRS();408 setState(SF_STATE_FAILURE);409 return;410 }411412 sent += ret;413 }414415 setState(SF_STATE_DATA_SENT);416 }417418 void receive_callback(s32 error)419 {420 if(error)421 {422 Ql_Debug_Trace("Failed to receive data! [%d]\r\n", error);423 setState(SF_STATE_FAILURE);424 return;425 }426427 // Read header428 s32 ret;429 do430 {431 ret = Sf_TCP_Recv((u8*)response + received, 511 - received);432433 // Blocking434 if(ret == SOC_WOULDBLOCK)435 return;436437 // Error438 else if(ret < 0)439 {440 Ql_Debug_Trace("Failed to receive data! [%d]\r\n", ret);441 setState(SF_STATE_FAILURE);442 return;443 }444445 received += ret;446 }

32

Page 41: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

447 while(ret != 0);448449 // Terminate response string.450 response[received] = '\0';451452 setState(SF_STATE_DATA_RECEIVED);453 }454455 #endif

sf_types.h1 /*2 * sf_types.h3 *4 * Created on: 7 apr 20155 * Author: Simon Nilsson6 */78 #ifndef SF_TYPES_H_9 #define SF_TYPES_H_1011 #include <math.h>1213 /**14 * Structure to hold a id/value-pair.15 */16 typedef struct {17 char id[20];18 float value;19 } ST_SENSOR;2021 #endif /* SF_TYPES_H_ */

sf_utility.c1 /*2 * sf_utility.c3 *4 * Created on: 30 mar 20155 * Author: Simon Nilsson6 */78 #include "ril.h"9 #include "ril_util.h"10 #include "ql_trace.h"11 #include "ql_stdlib.h"12 #include "ql_time.h"13 #include "ql_error.h"1415 #include "sf_utility.h"1617 typedef enum {

33

Page 42: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

18 REPEAT_NONE = 0,19 REPEAT_DAY = 1,20 REPEAT_WEEK = 2,21 REPEAT_MONTH = 322 }Enum_AlarmRepeat;2324 typedef enum {25 POWER_NONE = 0,26 POWER_OFF = 1,27 POWER_ON = 228 }Enum_AlarmPower;2930 static s32 imei_response(char* line, u32 len, void* userdata)31 {32 char* imei = userdata;3334 if (Ql_RIL_FindLine(line, len, "ERROR")35 || Ql_RIL_FindString(line, len, "+CME ERROR:")36 || Ql_RIL_FindString(line, len, "+CMS ERROR:"))37 {38 return RIL_ATRSP_FAILED;39 }40 else if(len > 0)41 {42 // Copy data43 Ql_strncpy(imei, line + 2, len - 4);4445 // Terminate string46 Ql_strcpy(imei + (len - 4), "\0");4748 return RIL_ATRSP_SUCCESS;49 }50 else51 return RIL_ATRSP_CONTINUE; //continue to wait52 }5354 static s32 battery_response(char *line, u32 len, void *userdata)55 {56 float *voltage = userdata;5758 char *head = Ql_RIL_FindString(line, len, "+CBC:");59 if(head)60 {61 char strTmp[10];62 char *start, *end;6364 // Seek past first parameter65 head = Ql_strstr(head, ",");6667 // Seek past second parameter68 start = Ql_strstr(head + 1, ",");69

34

Page 43: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

70 // Find end71 end = Ql_strstr(start + 1, "\r\n");7273 if (start && end)74 {75 Ql_memset(strTmp, 0x0, sizeof(strTmp));76 Ql_memcpy(strTmp, start + 1, end - start - 1);77 *voltage = Ql_atof(strTmp) / 1000.0;78 }79 return RIL_ATRSP_CONTINUE;80 }8182 head = Ql_RIL_FindLine(line, len, "OK");83 if(head)84 {85 return RIL_ATRSP_SUCCESS;86 }8788 head = Ql_RIL_FindLine(line, len, "ERROR");89 if(head)90 {91 return RIL_ATRSP_FAILED;92 }9394 head = Ql_RIL_FindString(line, len, "+CME ERROR:");95 if(head)96 {97 return RIL_ATRSP_FAILED;98 }99100 return RIL_ATRSP_CONTINUE;101 }102103 bool Sf_ErrorCheck(s32 ret, s32 expect, const char* msg)104 {105 if(ret != expect)106 {107 Ql_Debug_Trace("%s [%d]\r\n", msg, ret);108 return FALSE;109 }110 return TRUE;111 }112113 bool Sf_GetIMEI(char* imei)114 {115 return Sf_ErrorCheck(116 Ql_RIL_SendATCmd("AT+GSN", 6, imei_response , imei, 300),117 RIL_AT_SUCCESS ,118 "Failed to get IMEI!"119 );120 }121

35

Page 44: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

122 bool Sf_GetBatteryVoltage(float *voltage)123 {124 return Sf_ErrorCheck(125 Ql_RIL_SendATCmd("AT+CBC", 6, battery_response , voltage,

300),126 RIL_AT_SUCCESS ,127 "Failed to get battery voltage!"128 );129 }130131 bool Sf_SyncTime(void)132 {133 return Sf_ErrorCheck(134 Ql_RIL_SendATCmd("AT+CTZU=3", 9, NULL, NULL, 300),135 RIL_AT_SUCCESS ,136 "Failed to synchronize local time!"137 );138 }139140 bool Sf_EnableFullFunctionality(void)141 {142 return Sf_ErrorCheck(143 Ql_RIL_SendATCmd("AT+CFUN=1", 9, NULL, NULL, 15000),144 RIL_AT_SUCCESS ,145 "Failed to enable full functionality!"146 );147 }148149 s32 Sf_SetWakeupDelay(u32 seconds)150 {151 ST_Time currentTime , wakeUpTime;152153 // Get current ST_TIME.154 Ql_GetLocalTime(&currentTime);155156 Ql_Debug_Trace("<-- Time: %d/%d/%d %d:%d:%d %d -->\r\n",157 currentTime.year,158 currentTime.month,159 currentTime.day,160 currentTime.hour,161 currentTime.minute,162 currentTime.second,163 currentTime.timezone164 );165166 // Convert ST_TIME to seconds.167 u64 currentMKTime = Ql_Mktime(&currentTime);168169 // Make a new ST_TIME offset by seconds parameter.170 Ql_MKTime2CalendarTime(currentMKTime + seconds, &wakeUpTime)

;171

36

Page 45: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

172 // Build AT command.173 char cmd[39];174 Ql_sprintf(175 cmd,176 "AT+QALARM=1,\"%02d/%02d/%02d,%02d:%02d:%02d%+03d\",%d,%d",177 wakeUpTime.year % 100,178 wakeUpTime.month,179 wakeUpTime.day,180 wakeUpTime.hour,181 wakeUpTime.minute,182 wakeUpTime.second,183 wakeUpTime.timezone,184 REPEAT_NONE ,185 POWER_ON186 );187188 // Send command.189 s32 ret = Ql_RIL_SendATCmd(cmd, 38, NULL, NULL, 300);190 if(ret != QL_RET_OK)191 {192 Ql_Debug_Trace("Failed to set alarm! [%d]\r\n", ret);193 }194 else195 Ql_Debug_Trace("Module set to wake up in %d seconds.\r\n

", (u32)seconds);196197 return ret;198 }

sf_utility.h1 /*2 * sf_utility.h3 *4 * Created on: 30 mar 20155 * Author: Simon Nilsson6 */78 #ifndef SF_UTILITY_H_9 #define SF_UTILITY_H_1011 #include <math.h>12 #include "ql_type.h"1314 /**15 * Used to check return value from function.16 * @param ret Value returned by API function.17 * @param expect Expected value.18 * @param msg Error message.19 * @return TRUE if expected return value.20 */21 bool Sf_ErrorCheck(s32 ret, s32 expect, const char* msg);22

37

Page 46: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

23 /**24 * Gets the modules IMEI-number.25 * @param imei [out] IMEI-number, 16 bytes including null

termination.26 * @return TRUE if successful.27 */28 bool Sf_GetIMEI(char* imei);2930 /**31 * Gets the battery voltage level in Volts.32 * @param voltage [out] voltage level.33 * @return TRUE if successful.34 */35 bool Sf_GetBatteryVoltage(float *voltage);3637 /**38 * Requests network time synchronization.39 * @return TRUE if successful.40 */41 bool Sf_SyncTime(void);4243 /**44 * Enables full functionality mode.45 * @return TRUE if successful.46 */47 bool Sf_EnableFullFunctionality(void);4849 /**50 * Sets an alarm to wake up the module in a certain number of

seconds.51 * @param seconds Seconds until alarm.52 * @return 0 on success or a value from Enum_ATSndError.53 */54 s32 Sf_SetWakeupDelay(u32 seconds);5556 #endif /* SF_UTILITY_H_ */

sf_gps.h1 /*2 * sf_gps.h3 *4 * Created on: 7 may 20155 * Author: Simon Nilsson6 */78 #ifndef SF_GPS_H_9 #define SF_GPS_H_1011 #include "sf_types.h"1213 /**14 * Starts listening to GPS input.

38

Page 47: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

15 * @return TRUE on success.16 */17 bool Sf_GPS_Init(void);1819 /**20 * Stops listening to GPS input.21 */22 void Sf_GPS_Uninit(void);2324 /**25 * Attempts to read data from a GPS device.26 * @param datastreams [out] Array to hold values read from GPS.27 * @param streamCount [out] Counter for data28 * @return TRUE if GPS has a fix29 */30 bool Sf_GPS_Read(ST_SENSOR datastreams[], u8 *streamCount);3132 /**33 * Get status of GPS fix.34 * @return TRUE if GPS has a fix.35 */36 bool Sf_GPS_GetActive(void);3738 /**39 * Get most recent latitude40 * @return The latitude or 0 on failure.41 */42 float Sf_GPS_GetLatitude(void);4344 /**45 * Get most recent longitude46 * @return The longitude or 0 on failure.47 */48 float Sf_GPS_GetLongitude(void);4950 /**51 * Get most recent altitude in meters above sea level.52 * @return The altitude in meters.53 */54 float Sf_GPS_GetAltitude(void);5556 /**57 * Get most recent speed in knots.58 * @return Speed in knots.59 */60 float Sf_GPS_GetSpeed(void);6162 /**63 * Get most recent course in degrees.64 * @return Course in degrees.65 */66 float Sf_GPS_GetCourse(void);

39

Page 48: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

676869 #endif /* SF_GPS_H_ */

sf_gps.c1 /*2 * sf_gps.c3 *4 * Created on: 7 may 20155 * Author: Simon Nilsson6 */78 #include <math.h>9 #include "ql_stdlib.h"10 #include "ql_trace.h"11 #include "ql_uart.h"12 #include "ql_error.h"1314 #include "sf_utility.h"15 #include "sf_gps.h"1617 #define UART_BUFFER_SIZE 8318 static char uart_buffer[UART_BUFFER_SIZE];1920 static char gprmc[81];21 static char gpgga[81];2223 static void uart_callback(Enum_SerialPort port,

Enum_UARTEventType msg, bool level, void* customizedPara)24 {25 if(msg == EVENT_UART_READY_TO_READ)26 {27 Ql_memset(uart_buffer , 0, UART_BUFFER_SIZE);28 char c = 0;2930 while(Ql_UART_Read(port, (u8*)&c, 1))31 {32 if(c == '\r')33 {34 if(Ql_strstr(uart_buffer , "$GPRMC"))35 {36 Ql_strcpy(gprmc, uart_buffer);37 }38 else if(Ql_strstr(uart_buffer , "$GPGGA"))39 {40 Ql_strcpy(gpgga, uart_buffer);41 }42 }43 else if(c == '\n')44 {45 Ql_memset(uart_buffer , 0, UART_BUFFER_SIZE);46 }

40

Page 49: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

47 else48 {49 Ql_strncat(uart_buffer ,&c,1);50 }5152 }53 }54 }5556 static bool get_field(char *sentence , char *buffer, s8 position,

s8 size)57 {58 Ql_memset(buffer, 0, size);5960 char *start = sentence;6162 for(u8 i = 0; i < position; i++)63 {64 start = Ql_strchr(start, ',');6566 if(start)67 start++;68 else69 return FALSE;70 }7172 char *del = Ql_strchr(start, ',');7374 s8 len;75 if(del)76 len = del - start;77 else78 len = Ql_strlen(start);7980 if(len > 0 && len <= size)81 {82 Ql_memcpy(buffer, start, len);83 return TRUE;84 }8586 return FALSE;87 }8889 bool Sf_GPS_Init(void)90 {91 if(!Sf_ErrorCheck(92 Ql_UART_Register(UART_PORT3 , uart_callback , NULL),93 QL_RET_OK ,94 "Failed to register UART for GPS!"95 )) return FALSE;9697 return Sf_ErrorCheck(

41

Page 50: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

98 Ql_UART_Open(UART_PORT3 , 9600, FC_NONE),99 QL_RET_OK ,100 "Failed to open UART for GPS!"101 );102 }103104 void Sf_GPS_Uninit(void)105 {106 Ql_UART_Close(UART_PORT3);107 }108109 bool Sf_GPS_Read(ST_SENSOR datastreams[], u8 *streamCount)110 {111 if(Sf_GPS_GetActive())112 {113 // Latitude114 Ql_strcpy(datastreams[*streamCount].id, "lat");115 datastreams[*streamCount].value = Sf_GPS_GetLatitude();116 *streamCount += 1;117118 // Longitude119 Ql_strcpy(datastreams[*streamCount].id, "long");120 datastreams[*streamCount].value = Sf_GPS_GetLongitude();121 *streamCount += 1;122123 // Altitude124 Ql_strcpy(datastreams[*streamCount].id, "alt");125 datastreams[*streamCount].value = Sf_GPS_GetAltitude();126 *streamCount += 1;127128 // Speed129 Ql_strcpy(datastreams[*streamCount].id, "speed");130 datastreams[*streamCount].value = Sf_GPS_GetSpeed();131 *streamCount += 1;132133 // Course134 Ql_strcpy(datastreams[*streamCount].id, "course");135 datastreams[*streamCount].value = Sf_GPS_GetCourse();136 *streamCount += 1;137138 return TRUE;139 }140141 return FALSE;142 }143144 bool Sf_GPS_GetActive(void)145 {146 char status;147 return (get_field(gprmc, &status, 2, 1) && status == 'A');148 }149

42

Page 51: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

150 float Sf_GPS_GetLatitude(void)151 {152 char lat[10];153 char dir;154155 if(get_field(gprmc, lat, 3, 10))156 {157 char degrees[3] = "";158 Ql_strncpy(degrees, lat, 2);159160 float latitude = Ql_atoi(degrees) + (Ql_atof(lat + 2) /

60);161162 if(get_field(gprmc, &dir, 4, 1) && dir == 'S')163 latitude = -latitude;164165 return latitude;166 }167168 return 0;169 }170171 float Sf_GPS_GetLongitude(void)172 {173 char lng[11];174 char dir;175176 if(get_field(gprmc, lng, 5, 11))177 {178 char degrees[4] = "";179 Ql_strncpy(degrees, lng, 3);180181 float longitude = Ql_atoi(degrees) + (Ql_atof(lng + 3) /

60);182183 if(get_field(gprmc, &dir, 6, 1) && dir == 'W')184 longitude = -longitude;185186 return longitude;187 }188189 return 0;190 }191192 float Sf_GPS_GetAltitude(void)193 {194 char alt[11];195196 if(get_field(gpgga, alt, 9, 11))197 {198 return Ql_atof(alt);199 }

43

Page 52: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

200201 return 0;202 }203204 float Sf_GPS_GetSpeed(void)205 {206 char knots[11];207208 if(get_field(gprmc, knots, 7, 11))209 {210 return Ql_atof(knots);211 }212213 return 0;214 }215216 float Sf_GPS_GetCourse(void)217 {218 char course[11];219220 if(get_field(gprmc, course, 8, 11))221 {222 return Ql_atof(course);223 }224225 return 0;226 }

sf_iic.h1 /*2 * sf_iic.h3 *4 * Created on: 1 apr 20155 * Author: Simon Nilsson6 */78 #ifndef SF_IIC_H_9 #define SF_IIC_H_1011 #include "ql_type.h"12 #include "ql_gpio.h"1314 /**15 * Writes data to IIC bus.16 * @param address 7-bit address (upper 7 bits).17 * @param data The data.18 * @param length Length of data.19 * @return If no error, return the length of the write

data.20 * Negative integer indicates this function

fails.21 */

44

Page 53: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

22 s32 Sf_IIC_Write(u8 address, u8* data, u32 length);2324 /**25 * Reads data from IIC bus.26 * @param address 7-bit address (upper 7 bits).27 * @param buffer [out] Buffer to hold data.28 * @param length Bytes to read.29 * @return If no error, return the length of the read

data.30 * Negative integer indicates this function

fails.31 */32 s32 Sf_IIC_Read(u8 address, u8* buffer, u32 length);3334 /**35 * Combines a write and read operation on ICC bus.36 * @param address 7-bit address (upper 7 bits).37 * @param data The data.38 * @param dataLength Length of data.39 * @param buffer [out] Buffer to hold data.40 * @param length Bytes to read.41 * @return If no error, return the length of the read

data.42 * Negative integer indicates this function

fails.43 */44 s32 Sf_IIC_WriteRead(u8 address, u8 *data, s32 dataLength , u8 *

buffer, u32 length);4546 /**47 * Initializes the IIC bus.48 * @return TRUE if successful.49 */50 bool Sf_IIC_Init(void);5152 /**53 * Congigures the IIC bus for using address.54 * @param address 7-bit address (upper 7 bits).55 * @return TRUE if successful.56 */57 bool Sf_IIC_Config(u8 address);5859 /**60 * Uninitializes the IIC bus.61 * @return TRUE if successful.62 */63 bool Sf_IIC_Uninit(void);6465 #endif /* SF_IIC_H_ */

sf_iic.c1 /*

45

Page 54: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

2 * sf_iic.c3 *4 * Created on: 1 apr 20155 * Author: Simon Nilsson6 */78 #include "ql_type.h"9 #include "ql_gpio.h"10 #include "ql_iic.h"11 #include "ql_error.h"12 #include "ql_trace.h"13 #include "ql_stdlib.h"14 #include "ql_system.h"1516 #include "sf_iic.h"17 #include "sf_utility.h"1819 /**20 * Channel, can be 0~254.21 */22 static const u32 IIC_CHANNEL = 0;2324 /**25 * Controller only supports reading 7 bytes in one read,26 * not enough for SHT21.27 */28 static const u32 IIC_USE_CONTROLLER = FALSE;2930 /**31 * Speed is only relevant if using controller32 */33 static const u32 IIC_SPEED = 100;343536 s32 Sf_IIC_Write(u8 address, u8* data, u32 length)37 {38 return Ql_IIC_Write(IIC_CHANNEL , address, data, length);39 }4041 s32 Sf_IIC_Read(u8 address, u8* data, u32 length)42 {43 return Ql_IIC_Read(IIC_CHANNEL , address, data, length);44 }4546 s32 Sf_IIC_WriteRead(u8 address, u8 *data, s32 dataLength , u8 *

buffer, u32 length)47 {48 return Ql_IIC_Write_Read(IIC_CHANNEL , address, data,

dataLength , buffer, length);49 }5051 bool Sf_IIC_Init(void)

46

Page 55: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

52 {53 return Sf_ErrorCheck(54 Ql_IIC_Init(IIC_CHANNEL , PINNAME_RI , PINNAME_DCD ,

IIC_USE_CONTROLLER),55 QL_RET_OK ,56 "Failed to initialize IIC!"57 );58 }5960 bool Sf_IIC_Config(u8 address)61 {62 return Sf_ErrorCheck(63 Ql_IIC_Config(IIC_CHANNEL , TRUE, address, IIC_SPEED),64 QL_RET_OK ,65 "Failed to configure IIC!"66 );67 }6869 bool Sf_IIC_Uninit(void)70 {71 return Sf_ErrorCheck(72 Ql_IIC_Uninit(IIC_CHANNEL),73 QL_RET_OK ,74 "Failed to uninitialize IIC!"75 );76 }

sf_sht21.h1 /*2 * sf_sht21.h3 *4 * Created on: 7 apr 20155 * Author: Simon Nilsson6 */78 #ifndef SF_SHT21_H_9 #define SF_SHT21_H_1011 #include "ql_type.h"12 #include "sf_types.h"1314 /**15 * Attempts to read data from a SHT21 device.16 * @param sensors [out] Array to hold sensor values read

from devices.17 * @param sensorCount [out] Counter for sensors18 * @return TRUE if successful.19 */20 bool Sf_SHT21_Read(ST_SENSOR sensors[], u8 *sensorCount);2122 #endif /* SF_SHT21_H_ */

47

Page 56: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

sf_sht21.c1 /*2 * sf_sht21.c3 *4 * Created on: 7 apr 20155 * Author: Simon Nilsson6 */78 #include "ql_stdlib.h"9 #include "ql_error.h"10 #include "ql_trace.h"11 #include "ql_system.h"1213 #include "sf_utility.h"14 #include "sf_sht21.h"15 #include "sf_iic.h"1617 static const u8 SHT21_ADDR = 0x80;1819 static const u16 POLYNOMIAL = 0x131;2021 static bool check_crc(u8 data[], u8 length, u8 checksum)22 {23 u8 crc = 0;2425 //calculates 8-Bit checksum with given polynomial26 for (u8 i = 0; i < length; i++)27 {28 crc ^= (data[i]);2930 for (u8 bit = 8; bit > 0; --bit)31 {32 if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;33 else crc = (crc << 1);34 }35 }3637 return crc == checksum;38 }3940 static bool readID(char serial[])41 {42 u8 registerAddr[2] = {0xFA, 0x0F};43 u8 data[8];44 u8 buffer[8];4546 if(!Sf_ErrorCheck(47 Sf_IIC_WriteRead(SHT21_ADDR , registerAddr , 2, buffer, 8),48 8,49 "Failed to read register 0xFA 0x0F of SHT21!"50 )) return FALSE;51

48

Page 57: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

52 bool valid = TRUE;5354 data[5] = buffer[0];55 valid &= check_crc(buffer, 1, buffer[1]);56 data[4] = buffer[2];57 valid &= check_crc(buffer + 2, 1, buffer[3]);58 data[3] = buffer[4];59 valid &= check_crc(buffer + 4, 1, buffer[5]);60 data[2] = buffer[6];61 valid &= check_crc(buffer + 6, 1, buffer[7]);6263 registerAddr[0] = 0xFC;64 registerAddr[1] = 0xC9;65 if(!Sf_ErrorCheck(66 Sf_IIC_WriteRead(SHT21_ADDR , registerAddr , 2, buffer, 6),67 6,68 "Failed to read register 0xFC 0xC9 of SHT21!"69 )) return FALSE;7071 data[1] = buffer[0];72 data[0] = buffer[1];73 valid &= check_crc(buffer, 2, buffer[2]);74 data[7] = buffer[3];75 data[6] = buffer[4];76 valid &= check_crc(buffer + 3, 2, buffer[5]);7778 if(!valid)79 {80 Ql_Debug_Trace("SHT21 ID CRC Error.\r\n");81 return FALSE;82 }8384 // Convert serial to hex string.85 valid = FALSE;86 for(int i = 0; i < 8; i++)87 {88 if(data[i] != 0) valid = TRUE;89 Ql_sprintf(serial + i * 2, "%02X", data[7-i]);90 }9192 return valid;93 }9495 static bool readTemp(float *temp)96 {97 u8 cmd = 0xF3;98 u8 buffer[3];99100 // Send temperature measure command.101 if(!Sf_ErrorCheck(102 Sf_IIC_Write(SHT21_ADDR , &cmd, 1),103 1,

49

Page 58: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

104 "Failed to write temperature command to SHT21!"105 )) return FALSE;106107108 u8 i = 0;109 // Poll device untill data can be read.110 do111 {112 // Timeout after 200ms.113 if(++i >= 20)114 {115 Ql_Debug_Trace("SHT21 temperature read timed out.\r\n");116 return FALSE;117 }118119 // Sleep 10ms.120 Ql_Sleep(10);121122 } while(Sf_IIC_Read(SHT21_ADDR , buffer, 3) != 3);123124125 // Check CRC126 if(!check_crc(buffer, 2, buffer[2]))127 {128 Ql_Debug_Trace("SHT21 CRC Error while reading temperature.\r

\n");129 return FALSE;130 }131132 // Convert data bytes to u16 and clear bits [1..0] (status

bits)133 u16 result = (buffer[0] << 8) | (buffer[1] & 0xFC);134135 // Calculate temperature [C]136 *temp = -46.85 + 175.72/65536 * (float)result;137138 return TRUE;139 }140141 static bool readHumidity(float *rh)142 {143 u8 cmd = 0xF5;144 u8 buffer[3];145146 // Send moisture measure command.147 if(!Sf_ErrorCheck(148 Sf_IIC_Write(SHT21_ADDR , &cmd, 1),149 1,150 "Failed to write moisture command to SHT21!"151 )) return FALSE;152153 u8 i = 0;

50

Page 59: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

154 // Poll device untill data can be read.155 do156 {157 // Timeout after 200ms.158 if(++i >= 20)159 {160 Ql_Debug_Trace("SHT21 moisture read timed out.\r\n");161 return FALSE;162 }163164 // Sleep 10ms.165 Ql_Sleep(10);166167 } while(Sf_IIC_Read(SHT21_ADDR , buffer, 3) != 3);168169 // Check CRC170 if(!check_crc(buffer, 2, buffer[2]))171 {172 Ql_Debug_Trace("SHT21 CRC Error while reading moisture.\r\n"

);173 return FALSE;174 }175176 // Convert data bytes to u16 and clear bits [1..0] (status

bits)177 u16 result = (buffer[0] << 8) | (buffer[1] & 0xFC);178179 // Calculate relative humidity [%RH]180 *rh = -6.0 + 125.0/65536 * (float)result;181182 return TRUE;183 }184185 bool Sf_SHT21_Read(ST_SENSOR sensors[], u8 *sensorCount)186 {187 if(Sf_IIC_Config(SHT21_ADDR))188 {189 char serial[17] = {'\0'};190 float value = 0;191192 Ql_Debug_Trace("Checking for SHT21 device...\r\n");193194 if(readID(serial))195 {196 Ql_Debug_Trace("SHT21 ID: %s\r\n", serial);197198 // Add temperature measurement199 if(readTemp(&value))200 {201 Ql_sprintf(sensors[*sensorCount].id, "%s-t", serial);202 sensors[*sensorCount].value = value;

51

Page 60: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

203 Ql_Debug_Trace("SHT21 Temp: %f\r\n", sensors[*sensorCount].value);

204 *sensorCount += 1;205 }206207 // Add relative humidity measurement208 if(readHumidity(&value))209 {210 Ql_sprintf(sensors[*sensorCount].id, "%s-r", serial);211 sensors[*sensorCount].value = value;212 Ql_Debug_Trace("SHT21 Moisture: %f\r\n", sensors[*

sensorCount].value);213 *sensorCount += 1;214 }215216 return TRUE;217 }218 }219 else220 Ql_Debug_Trace("Failed to configure IIC for SHT21!\r\n");221222 return FALSE;223 }

sf_json.h1 /*2 * sf_json.h3 *4 * Created on: 23 apr 20155 * Author: Simon Nilsson6 */78 #ifndef SF_JSON_H_9 #define SF_JSON_H_1011 #include "ql_type.h"12 #include "sf_types.h"1314 /**15 * Compiles data into JSON.16 * @param json [out] Buffer large enough to hold data.17 * @param imei IMEI-number.18 * @param datastreams Array of datastreams.19 * @param sensorCount Length of datastreams -array in bytes.20 * @return Length of output in bytes.21 */22 s32 Sf_JSON_Build(char *json, const char *imei, ST_SENSOR

datastreams[], u32 sensorCount);2324 /**25 * Tries to extract parameters from JSON data.26 * @param data The data.

52

Page 61: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

27 * @param dataLength Length of data in bytes.28 * @param s [out] s parameter.29 * @param log [out] log parameter.30 * @param update [out] Update url if available.31 * @return TRUE if any parameter was found.32 */33 bool Sf_JSON_Parse(const char *data, s32 *s, s32 *log, char *

update);3435 #endif /* SF_JSON_H_ */

sf_json.c1 /*2 * sf_json.c3 *4 * Created on: 23 apr 20155 * Author: Simon Nilsson6 */78 #include "ql_stdlib.h"9 #include "ql_trace.h"10 #include "ql_error.h"1112 #include "sf_config.h"13 #include "sf_json.h"1415 static char* find(const char *json, const char *name)16 {17 char searchString[32];1819 // Build search string.20 s32 len = Ql_sprintf(searchString , "\"%s\":", name);2122 // Find start23 char *start = Ql_strstr(json, searchString);2425 if(start)26 return start + len;2728 return start;29 }3031 static bool parseInteger(const char *json, const char * name,

s32 *value)32 {33 *value = 0;3435 // Find start36 char *start = find(json, name);37 if(start)38 {39 // Calculate length.

53

Page 62: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

40 // Find whatever comes first ',' or '}'.41 s32 curlyBrace = Ql_strstr(start, "}") - start;42 s32 len = Ql_strstr(start, ",") - start;43 if(curlyBrace < len) len = curlyBrace;4445 if(len > 0 && len < 11)46 {47 // Extract string.48 char strTemp[11];49 Ql_strncpy(strTemp, start, len);50 strTemp[len] = '\0';5152 // Parse value.53 *value = Ql_atoi(strTemp);5455 return TRUE;56 }57 }58 return FALSE;59 }6061 static bool parseString(const char *json, const char * name,

char *buffer)62 {63 buffer[0] = '\0';6465 // Find start66 char *start = find(json, name);67 if(start)68 {69 // step over ".70 start++;7172 // Calculate length.73 // Find ending ".74 char *end = Ql_strstr(start, "\"");7576 if(end > start)77 {78 // Extract string.79 Ql_strncpy(buffer, start, end - start);80 buffer[end - start] = '\0';8182 return TRUE;83 }84 }85 return FALSE;86 }8788 s32 Sf_JSON_Build(char *json, const char *imei, ST_SENSOR

datastreams[], u32 sensorCount)89 {

54

Page 63: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

90 // Keep track of length.91 s32 len = 0;9293 // Start of data.94 len += Ql_sprintf(9596 // Buffer97 json,9899 // Format100 "{\"version\":\"%s\",\"IMEI\":\"%s\",\"datastreams\":[",101102 // API Version.103 SF_VERSION ,104105 // IMEI106 imei107108 );109110 // Sensor data.111 for (u32 i = 0; i < sensorCount; i++)112 {113 len += Ql_sprintf(114115 // Buffer116 json + len,117118 // Format119 "{\"id\":\"%s\",\"val\":\"%f\"}%s",120121 // Id122 datastreams[i].id,123124 // Value125 datastreams[i].value,126127 // Add comma if not last item.128 (i < sensorCount - 1) ? "," : ""129130 );131 }132133 // End of data.134 len += Ql_sprintf(json + len, "]}");135136 // Return data length.137 return len;138 }139140 bool Sf_JSON_Parse(const char *data, s32 *s, s32 *log, char *

update)

55

Page 64: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

141 {142 bool found = FALSE;143144 // s parameter145 // Seconds to sleep146 // Example: 3600147 // Integer between 300 (5min) and 32400 (9h)148 found |= parseInteger(data, "s", s);149150 // log parameter151 // Log interval in seconds152 // Example: 20153 // Integer154 found |= parseInteger(data, "log", log);155156 // update parameter157 // FTP or HTTP url to update package158 // Example: "http://example.com/update.bin"159 // String160 found |= parseString(data, "update", update);161162 return found;163 }

sf_tcp.h1 /*2 * sf_tcp.h3 *4 * Created on: 7 apr 20155 * Author: Simon Nilsson6 */78 #ifndef SF_CONNECTION_H_9 #define SF_CONNECTION_H_1011 #include "ql_type.h"1213 /**14 * Activates GPRS to enable data communication.15 * @return TRUE if successful.16 */17 bool Sf_ActivateGPRS(void);1819 /**20 * Deactivates GPRS.21 * @return TRUE if successful.22 */23 bool Sf_DeactivateGPRS(void);2425 /**26 * Retrieves associated ip from hostname.27 * @param hostname The hostname.

56

Page 65: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

28 * @param ip [out] IP-address.29 * @return TRUE if successful.30 */31 bool Sf_GetIP(const char* hostname, u32 *ip);3233 /**34 * Connects to a server.35 * @param ip Server ip.36 * @param port Server port.37 * @param read Callback function for reading response.38 * @param write Callback function for writing data.39 * @return TRUE if successful.40 */41 bool Sf_TCP_Connect(u32 ip, u16 port, void (*read)(s32), void (*

write)(s32));4243 /**44 * Disconnects from server.45 * @return TRUE if successful.46 */47 bool Sf_TCP_Disconnect(void);4849 /**50 * Sends data to server.51 * @param data The data.52 * @param length Bytes to send.53 * @return Number of bytes sent or a value fron

Enum_SocErrCode.54 */55 s32 Sf_TCP_Send(u8 *data, s32 length);5657 /**58 * Recieve data from server.59 * @param buffer [out] The receive buffer.60 * @param length Bytes to read.61 * @return Number of bytes received or value fron

Enum_SocErrCode.62 */63 s32 Sf_TCP_Recv(u8 *buffer, s32 length);6465 #endif /* SF_CONNECTION_H_ */

sf_tcp.c1 /*2 * sf_tcp.c3 *4 * Created on: 7 apr 20155 * Author: Simon Nilsson6 */78 #include "custom_feature_def.h"9 #include "ril.h"

57

Page 66: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

10 #include "ql_type.h"11 #include "ql_gprs.h"12 #include "ql_socket.h"13 #include "ql_trace.h"14 #include "ql_error.h"15 #include "ql_stdlib.h"16 #include "ql_system.h"1718 #include "sf_config.h"19 #include "sf_tcp.h"2021 static ST_GprsConfig config = {2223 // APN24 SF_APN,2526 // Username27 "",2829 // Password30 "",3132 // Authentication type33 0,3435 // Reserved36 NULL,37 NULL,38 };3940 /**41 * Not used42 */43 static ST_PDPContxt_Callback callback_gprs_func = {44 NULL,45 NULL46 };4748 /**49 * Callbacks50 */51 static void (*callback_read)(s32 error);52 static void (*callback_write)(s32 error);5354 static void tcp_read(s32 socketId, s32 errCode, void*

customParam)55 {56 callback_read(errCode);57 }5859 static void tcp_write(s32 socketId, s32 errCode, void*

customParam)

58

Page 67: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

60 {61 callback_write(errCode);62 }6364 static ST_SOC_Callback callback_soc_func = {65 NULL,66 NULL,67 NULL,68 tcp_read ,69 tcp_write70 };7172 /**73 * PDP Context Id74 */75 static s32 pdpCtxId;7677 /**78 * Socket Id79 */80 static s32 socketId;81828384 bool Sf_ActivateGPRS(void)85 {86 s32 ret;8788 // Get PDP Context.89 ret = Ql_GPRS_GetPDPContextId();90 if (ret == GPRS_PDP_ERROR)91 {92 Ql_Debug_Trace("No PDP context available!\r\n");93 return FALSE;94 }95 else96 pdpCtxId = ret;9798 // Register callbacks99 ret = Ql_GPRS_Register(pdpCtxId , &callback_gprs_func , NULL);100 if (ret != GPRS_PDP_SUCCESS)101 {102 Ql_Debug_Trace("Failed to register GPRS callbacks! [%d]\r\n"

, ret);103 return FALSE;104 }105106 // Configure PDP.107 ret = Ql_GPRS_Config(pdpCtxId , &config);108 if (ret != GPRS_PDP_SUCCESS)109 {

59

Page 68: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

110 Ql_Debug_Trace("Failed to configure GPRS PDP! [%d]\r\n", ret);

111 return FALSE;112 }113114 // Activate GPRS.115 ret = Ql_GPRS_ActivateEx(pdpCtxId , TRUE);116 if(ret != GPRS_PDP_SUCCESS)117 {118 Ql_Debug_Trace("Failed to activate GPRS! [%d]\r\n", ret);119 return FALSE;120 }121122 return TRUE;123 }124125 bool Sf_DeactivateGPRS(void)126 {127 // Deactivate GPRS.128 s32 ret = Ql_GPRS_DeactivateEx(pdpCtxId , TRUE);129 if(ret != GPRS_PDP_SUCCESS)130 {131 Ql_Debug_Trace("Failed to deactivate GPRS! [%d]\r\n", ret);132 return FALSE;133 }134135 return TRUE;136 }137138 bool Sf_GetIP(const char* hostname, u32 *ip)139 {140 s32 ret = 0;141 u32 ipCount = 0;142 u32 ipAddress[5];143144 // Get server IP.145 ret = Ql_IpHelper_GetIPByHostNameEx(pdpCtxId , 0, (u8*)hostname

, ipAddress , &ipCount);146 if(ret != SOC_SUCCESS || ipCount < 1)147 {148 Ql_Debug_Trace("Failed to get IP for hostname \"%s\"! [%d]\r

\n", hostname , ret);149 return FALSE;150 }151152 *ip = ipAddress[0];153 return TRUE;154 }155156 bool Sf_TCP_Connect(u32 ip, u16 port, void (*read)(s32), void (*

write)(s32))157 {

60

Page 69: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

158 s32 ret;159160 callback_read = read;161 callback_write = write;162163 // Register socket callbacks.164 ret = Ql_SOC_Register(callback_soc_func , NULL);165 if (ret != SOC_SUCCESS)166 {167 Ql_Debug_Trace("Failed to register socket callbacks! [%d

]\r\n", ret);168 return FALSE;169 }170171 // Create socket.172 ret = Ql_SOC_Create(pdpCtxId, SOC_TYPE_TCP);173 if (ret < 0)174 {175 Ql_Debug_Trace("Failed to create socket! [%d]\r\n", ret)

;176 return FALSE;177 }178 else179 socketId = ret;180181 // NOTE: ConnectEx takes pointer to 4 byte IP-address casted

to u32.182 // It's strange but it works.183184 // Connect to server.185 ret = Ql_SOC_ConnectEx(socketId , (u32)&ip, port, TRUE);186 if (ret != SOC_SUCCESS)187 {188 Ql_Debug_Trace("Failed to connect! [%d]\r\n", ret);189 return FALSE;190 }191192 return TRUE;193 }194195 bool Sf_TCP_Disconnect(void)196 {197 // Close socket.198 s32 ret = Ql_SOC_Close(socketId);199 if (ret != SOC_SUCCESS)200 {201 Ql_Debug_Trace("Failed to close socket! [%d]\r\n", ret);202 return FALSE;203 }204205 return TRUE;206 }

61

Page 70: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

207208 s32 Sf_TCP_Send(u8 *data, s32 length)209 {210 return Ql_SOC_Send(socketId , data, length);211 }212213 s32 Sf_TCP_Recv(u8 *buffer, s32 length)214 {215 return Ql_SOC_Recv(socketId , buffer, length);216 }

sf_http.h1 /*2 * sf_http.h3 *4 * Created on: 7 apr 20155 * Author: Simon Nilsson6 */78 #ifndef SF_HTTP_H_9 #define SF_HTTP_H_1011 #include "ql_type.h"1213 /**14 * HTTP Port15 */16 const u16 HTTP_PORT;1718 /**19 * Sends a HTTP request to preconfigured server.20 * @param url Url.21 * @param type Request type.22 * @param dataLength Length of data.23 * @param callback Callback function for writing data.24 * @return TRUE if successful.25 */26 bool Sf_HTTP_SendRequest(const char *url, const char *type, s32

dataLength , void (*callabck)(s32 error));2728 /**29 * Sends a HTTP request to preconfigured server.30 * @param callback Callback function for reading response.31 */32 void Sf_HTTP_GetResponse(void (*callback)(s32 error));3334 #endif /* SF_HTTP_H_ */

sf_http.c1 /*2 * sf_http.c

62

Page 71: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

3 *4 * Created on: 7 apr 20155 * Author: Simon Nilsson6 */78 #include "ql_stdlib.h"9 #include "ql_trace.h"10 #include "ql_error.h"11 #include "ql_socket.h"1213 #include "sf_config.h"14 #include "sf_http.h"15 #include "sf_tcp.h"1617 const u16 HTTP_PORT = 80;1819 static char header[128];20 static s32 headerLength;21 static s32 sent;22 static u8 receivedHeaderEnd;2324 /**25 * Callbacks26 */27 static void (*callback_read)(s32 error);28 static void (*callback_write)(s32 error);2930 static void http_write(s32 error)31 {32 if(error)33 {34 callback_write(error);35 return;36 }3738 // Send header39 while(sent < headerLength)40 {41 s32 ret = Sf_TCP_Send((u8*)header + sent, headerLength -

sent);4243 // Blocking44 if(ret == SOC_WOULDBLOCK)45 return;4647 // Error48 else if(ret < 0)49 {50 callback_write(ret);51 return;52 }53

63

Page 72: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

54 sent += ret;55 }5657 // Send data58 callback_write(error);59 }6061 static void http_read(s32 error)62 {63 if(error)64 {65 callback_read(error);66 return;67 }6869 // Read header70 while(receivedHeaderEnd != 4)71 {72 u8 c;73 s32 ret = Sf_TCP_Recv(&c, 1);7475 // Blocking76 if(ret == SOC_WOULDBLOCK)77 return;7879 // Error80 else if(ret < 0)81 {82 callback_read(ret);83 return;84 }8586 // Check for end (\r\n\r\n)87 if(ret == 1)88 {89 if(c == '\r' || c == '\n')90 receivedHeaderEnd++;91 else92 receivedHeaderEnd = 0;93 }94 }9596 // Receive data97 callback_read(error);9899 }100101 void makeHeader(const char *host, const char *path, const char *

type, s32 contentLength)102 {103 headerLength = Ql_sprintf(104

64

Page 73: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

105 // Buffer106 header,107108 // Format109 "%s %s HTTP/1.1\r\n"110 "Host: %s\r\n"111 "Content-Length: %d\r\n"112 "Connection: Close\r\n"113 "\r\n",114115 // Request type.116 type,117118 // Path119 path,120121 // Host122 host,123124 // Content-Length125 contentLength126 );127 }128129 bool Sf_HTTP_SendRequest(const char *url, const char *type, s32

dataLength , void (*callback)(s32))130 {131 callback_write = callback;132133 char host[100];134 char path[100];135 sent = 0;136137 if(Ql_sscanf(url, "%99[^/]%99[^\n]", host, path) == 2)138 {139140 // Prepare header141 makeHeader(host, path, type, dataLength);142143 // Get IP144 u32 ip;145 if(Sf_GetIP(host, &ip))146 {147 u8 *ip8 = (u8*)&ip;148 Ql_Debug_Trace(149 "Remote Address: %d.%d.%d.%d:%d\r\n",150 ip8[0], ip8[1], ip8[2], ip8[3], HTTP_PORT151 );152153 // Connect154 if(Sf_TCP_Connect(ip, HTTP_PORT , http_read , http_write))155 {

65

Page 74: Remote measuring and logging - Evaluation of the Quectel ...832270/FULLTEXT01.pdf · Remotemeasuringandlogging-EvaluationoftheQuectelOpenCPU technology SimonNilsson 2015-06-11 1 Introduction

Remote measuring and logging - Evaluation of the Quectel OpenCPUtechnologySimon Nilsson 2015-06-11

156 Ql_Debug_Trace("<-- Connection successful -->\r\n");157 http_write(0);158 return TRUE;159 }160 }161 else Ql_Debug_Trace("Unable to get IP for \"%s\"!\r\n", host

);162 }163 else Ql_Debug_Trace("Unable to parse URL \"%s\"!\r\n", url);164165 return FALSE;166 }167168 /**169 * Sends a HTTP request to preconfigured server.170 * @param callback Callback function for reading response.171 */172 void Sf_HTTP_GetResponse(void (*callback)(s32 error))173 {174 callback_read = callback;175 receivedHeaderEnd = 0;176 http_read(0);177 }

66