From c3e4c9a25c2910d2d66d52215b3406b13d5b23d5 Mon Sep 17 00:00:00 2001 From: Yuval Adam Date: Sun, 29 Jun 2014 12:34:32 +0300 Subject: Add more board models --- boards/dk-tm4c129x/qs_weather/json.c | 843 +++++++++++++++++++++++++++++++++++ 1 file changed, 843 insertions(+) create mode 100644 boards/dk-tm4c129x/qs_weather/json.c (limited to 'boards/dk-tm4c129x/qs_weather/json.c') diff --git a/boards/dk-tm4c129x/qs_weather/json.c b/boards/dk-tm4c129x/qs_weather/json.c new file mode 100644 index 0000000..1f71bc7 --- /dev/null +++ b/boards/dk-tm4c129x/qs_weather/json.c @@ -0,0 +1,843 @@ +//***************************************************************************** +// +// json.c - File to handle json formatted data from websites. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** +#include +#include +#include +#include +#include "utils/ustdlib.h" +#include "utils/lwiplib.h" +#include "eth_client.h" +#include "json.h" +#include "images.h" + +//**************************************************************************** +// +// The locally defined lwIP buffer parsing pointer. +// +//**************************************************************************** +typedef struct +{ + // + // A pbuf pointer from lwIP. + // + struct pbuf *psBuf; + + // + // The current index into the pbuf pointer. + // + uint32_t ui32Idx; +} +tBufPtr; + +//**************************************************************************** +// +// Initialize a buffer parsing pointer. +// +//**************************************************************************** +static void +BufPtrInit(tBufPtr *psBufPtr, struct pbuf *psBuf) +{ + psBufPtr->psBuf = psBuf; + psBufPtr->ui32Idx = 0; +} + +//**************************************************************************** +// +// Get a single byte from a parsing pointer. +// +//**************************************************************************** +static uint8_t +BufData8Get(tBufPtr *psBufPtr) +{ + return(((uint8_t *)psBufPtr->psBuf->payload)[psBufPtr->ui32Idx]); +} + +//***************************************************************************** +// +// Increment a parsing pointer by a given value. +// +//***************************************************************************** +uint32_t +BufPtrInc(tBufPtr *psBufPtr, uint32_t ui32Inc) +{ + psBufPtr->ui32Idx += ui32Inc; + + if(psBufPtr->ui32Idx >= psBufPtr->psBuf->len) + { + psBufPtr->ui32Idx = 0; + + psBufPtr->psBuf = psBufPtr->psBuf->next; + + if(psBufPtr->psBuf == 0) + { + ui32Inc = 0; + } + } + return(ui32Inc); +} + +//***************************************************************************** +// +// Return the image to use for the given icon returned from the weather update. +// +//***************************************************************************** +void +GetImage(char *pcIcon, const uint8_t **ppui8Image, const char **ppcDescription) +{ + static const struct + { + char pcId[2]; + const uint8_t *pui8Image; + const char *pcDescription; + } + pcIconTable[9] = + { + // + // Clear Sky. + // + { "01", g_pui8SunImage, "Clear Sky"}, + + // + // Light Clouds. + // + { "02", g_pui8CloudyImage, "Light Clouds"}, + + // + // Scattered Clouds. + // + { "03", g_pui8CloudyImage, "Scattered Clouds"}, + + // + // Broken Clouds. + // + { "04", g_pui8CloudyImage, "Broken Clouds"}, + + // + // Rain showers. + // + { "09", g_pui8RainImage, "Light Rain"}, + + // + // Rain. + // + { "10", g_pui8RainImage, "Rain"}, + + // + // Thunderstorms. + // + { "11", g_pui8ThuderStormImage, "Thunderstorms"}, + + // + // Snow. + // + { "13", g_pui8SnowImage, "Snow"}, + + // + // Mist/Fog. + // + { "50", g_pui8FogImage, "Mist/Fog"}, + }; + int32_t i32Idx; + + for(i32Idx = 0; i32Idx < 9; i32Idx++) + { + if((pcIcon[0] == pcIconTable[i32Idx].pcId[0]) && + (pcIcon[1] == pcIconTable[i32Idx].pcId[1])) + { + *ppui8Image = pcIconTable[i32Idx].pui8Image; + *ppcDescription = pcIconTable[i32Idx].pcDescription; + break; + } + } +} + +//***************************************************************************** +// +// Compare a string at the current location of a parsing pointer. +// +//***************************************************************************** +uint32_t +CompareString(tBufPtr *psBufPtr, const char *pcField, uint32_t ui32Size) +{ + uint32_t ui32Idx; + + for(ui32Idx = 0; ui32Idx < ui32Size; ui32Idx++) + { + if(BufData8Get(psBufPtr) == pcField[ui32Idx]) + { + if(BufPtrInc(psBufPtr, 1) != 1) + { + break; + } + } + else + { + break; + } + } + + if(ui32Idx == ui32Size) + { + return(0); + } + + return(1); +} + +//***************************************************************************** +// +// This function searches for a field from the JSON data. The field should be +// quoted in the data and immediately follow a '{' character. This can be used +// to also search for sub data in another field if the pointer to the data for +// the parent field. +// +//***************************************************************************** +static uint32_t +GetField(char *pcField, tBufPtr *psBufPtr) +{ + uint32_t ui32Curly, ui32Quote; + int32_t i32NewItem; + + ui32Curly = 0; + i32NewItem = 0; + ui32Quote = 0; + + while(1) + { + if(BufData8Get(psBufPtr) == '{') + { + ui32Curly++; + } + else if(BufData8Get(psBufPtr) == '}') + { + ui32Curly--; + + if(ui32Curly == 1) + { + ui32Quote = 0; + } + } + else if(BufData8Get(psBufPtr) == ',') + { + if((ui32Curly == 1) && ((ui32Quote & 1) == 0)) + { + ui32Quote = 0; + } + } + else if(BufData8Get(psBufPtr) == '"') + { + if((ui32Curly == 1) && (ui32Quote == 0)) + { + i32NewItem = 1; + } + ui32Quote++; + } + + if(BufPtrInc(psBufPtr, 1) != 1) + { + break; + } + + if(i32NewItem) + { + i32NewItem = 0; + if(CompareString(psBufPtr, pcField, ustrlen(pcField)) == 0) + { + while(1) + { + if(BufData8Get(psBufPtr) == ':') + { + if(BufPtrInc(psBufPtr, 1) != 1) + { + break; + } + return(1); + } + + if(BufPtrInc(psBufPtr, 1) != 1) + { + break; + } + } + return(0); + } + } + } + return(0); +} + +//***************************************************************************** +// +// This function searches for a value in a JSON item as an integer. These are +// non-quoted values so if the number is a quoted integer this function returns +// -1. If the value is found then it is returned by this function. +// +//***************************************************************************** +int32_t +GetFieldValueInt(tBufPtr *psBufPtr) +{ + int32_t i32Idx; + char pcTemp[20]; + const char *pEnd; + + i32Idx = 0; + + while(1) + { + // + // Find the end of this item. + // + if((BufData8Get(psBufPtr) == '}') || (BufData8Get(psBufPtr) == ',')) + { + // + // null terminate the string and get the value from the string in + // decimal. + // + pcTemp[i32Idx] = 0; + return(ustrtoul(pcTemp, &pEnd, 10)); + } + + // + // Should not hit a " char or something went wrong. + // + if(BufData8Get(psBufPtr) == '"') + { + break; + } + + // + // Copy the string to the local variable. + // + pcTemp[i32Idx] = BufData8Get(psBufPtr); + + if((pcTemp[i32Idx] == '\r') || (pcTemp[i32Idx] == '\n')) + { + pcTemp[i32Idx] = 0; + } + else + { + i32Idx++; + } + + if(BufPtrInc(psBufPtr, 1) != 1) + { + break; + } + + // + // Number was too large to represent. + // + if(i32Idx >= sizeof(pcTemp)) + { + break; + } + } + return(INVALID_INT); +} + +//***************************************************************************** +// +// This function searches for a value in a JSON item as quoted value. These +// values are quoted values so if the number is not a quoted value this +// function returns -1. If the quoted value is found then it is returned in +// the pcDataDest array. +// +//***************************************************************************** +int32_t +GetFieldValueString(tBufPtr *psBufPtr, char *pcDataDest, uint32_t ui32SizeDest) +{ + int32_t i32OutIdx; + + // + // The value should always start with a " char or something went wrong. + // + if(BufData8Get(psBufPtr) != '"') + { + return(-1); + } + + // + // Skip the initial " char. + // + if(BufPtrInc(psBufPtr, 1) != 1) + { + return(-1); + } + + for(i32OutIdx = 0; i32OutIdx < ui32SizeDest;) + { + // + // Either a '}', ',', or '"' ends an item. + // + if((BufData8Get(psBufPtr) == '}') || + (BufData8Get(psBufPtr) == ',') || + (BufData8Get(psBufPtr) == '"')) + { + // + // Null terminate the string and return. + // + pcDataDest[i32OutIdx] = 0; + return(i32OutIdx); + } + + // + // Continue coping chars into the destination buffer. + // + pcDataDest[i32OutIdx] = BufData8Get(psBufPtr); + + // + // These can occur in the response string and need to be ignored. + // + if((pcDataDest[i32OutIdx] == '\r') || (pcDataDest[i32OutIdx] == '\n')) + { + pcDataDest[i32OutIdx] = 0; + } + else + { + i32OutIdx++; + } + + if(BufPtrInc(psBufPtr, 1) != 1) + { + break; + } + } + + // + // Make sure to null terminate inside the current string. + // + if(i32OutIdx == ui32SizeDest) + { + pcDataDest[i32OutIdx-1] = 0; + return(i32OutIdx - 1); + } + return(-1); +} + +//***************************************************************************** +// +// Fill out the psWeatherReport structure from data returned from the JSON +// query. +// +//***************************************************************************** +int32_t +JSONParseForecast(uint32_t ui32Index, tWeatherReport *psWeatherReport, + struct pbuf *psBuf) +{ + tBufPtr sBufPtr, sBufList, sBufTemp; + char pcCode[4]; + int32_t i32Items,i32Code; + + + // + // Reset the pointers. + // + BufPtrInit(&sBufPtr, psBuf); + + // + // Check and see if the request was valid. + // + if(GetField("cod", &sBufPtr) != 0) + { + // + // Check for a 404 not found error. + // + sBufTemp = sBufPtr; + + // + // Check for a 404 not found error. + // + i32Code = GetFieldValueInt(&sBufTemp); + + sBufTemp = sBufPtr; + + if(i32Code != INVALID_INT) + { + if(i32Code == 404) + { + return(-1); + } + } + else if(GetFieldValueString(&sBufTemp, pcCode, sizeof(pcCode)) >= 0) + { + // + // Check for a 404 not found error. + // + if(ustrncmp(pcCode, "404", 3) == 0) + { + return(-1); + } + } + } + + // + // Reset the pointers. + // + BufPtrInit(&sBufPtr, psBuf); + + // + // Initialize the number of items found. + // + i32Items = 0; + + if(GetField("list", &sBufPtr) != 0) + { + // + // Save the list pointer. + // + sBufList = sBufPtr; + + // + // Get the humidity. + // + if(GetField("humidity", &sBufPtr) != 0) + { + psWeatherReport->i32Humidity = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->i32Humidity = INVALID_INT; + } + + // + // Reset the pointer to the start of the list values. + // + sBufPtr = sBufList; + + // + // Get the average daily pressure. + // + if(GetField("pressure", &sBufPtr) != 0) + { + psWeatherReport->i32Pressure = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->i32Pressure = INVALID_INT; + } + + // + // Reset the pointer to the start of the list values. + // + sBufPtr = sBufList; + + // + // Get the average daily temperature. + // + if(GetField("temp", &sBufPtr) != 0) + { + if(GetField("day", &sBufPtr) != 0) + { + psWeatherReport->i32Temp = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->i32Temp = INVALID_INT; + } + } + + // + // Reset the pointer to the start of the list values. + // + sBufPtr = sBufList; + + // + // Get the low temperature. + // + if(GetField("temp", &sBufPtr) != 0) + { + if(GetField("min", &sBufPtr) != 0) + { + psWeatherReport->i32TempLow = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->i32TempLow = INVALID_INT; + } + } + + // + // Reset the pointer to the start of the list values. + // + sBufPtr = sBufList; + + // + // Get the high temperature. + // + if(GetField("temp", &sBufPtr) != 0) + { + if(GetField("max", &sBufPtr) != 0) + { + psWeatherReport->i32TempHigh = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->i32TempHigh = INVALID_INT; + } + } + // + // Reset the pointer to the start of the list values. + // + sBufPtr = sBufList; + + if(GetField("dt", &sBufPtr) != 0) + { + psWeatherReport->ui32Time = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->ui32Time = 0; + } + } + + return(i32Items); +} + +//***************************************************************************** +// +// Fill out the psWeatherReport structure from data returned from the JSON +// query. +// +//***************************************************************************** +int32_t +JSONParseCurrent(uint32_t ui32Index, tWeatherReport *psWeatherReport, + struct pbuf *psBuf) +{ + tBufPtr sBufPtr, sBufMain, sBufTemp; + char pcIcon[3]; + char pcCode[4]; + int32_t i32Items, i32Code; + + // + // Reset the pointers. + // + BufPtrInit(&sBufPtr, psBuf); + + // + // Check and see if the request was valid. + // + if(GetField("cod", &sBufPtr) != 0) + { + sBufTemp = sBufPtr; + + // + // Check for a 404 not found error. + // + i32Code = GetFieldValueInt(&sBufTemp); + + sBufTemp = sBufPtr; + + if(i32Code != INVALID_INT) + { + if(i32Code == 404) + { + return(-1); + } + } + else if(GetFieldValueString(&sBufTemp, pcCode, sizeof(pcCode)) >= 0) + { + // + // Check for a 404 not found error. + // + if(ustrncmp(pcCode, "404", 3) == 0) + { + return(-1); + } + } + } + + // + // Initialize the number of items that have been found. + // + i32Items = 0; + + // + // Reset the pointers. + // + BufPtrInit(&sBufPtr, psBuf); + + // + // Find the basic weather description(weather.description). + // + if(GetField("weather", &sBufPtr) != 0) + { + if(GetField("icon", &sBufPtr) != 0) + { + if(GetFieldValueString(&sBufPtr, pcIcon, sizeof(pcIcon)) > 0) + { + // + // Save the image pointer. + // + GetImage(pcIcon, &psWeatherReport->pui8Image, + &psWeatherReport->pcDescription); + + i32Items++; + } + else + { + // + // No image was found. + // + psWeatherReport->pui8Image = 0; + } + } + } + + // + // Reset the pointers. + // + BufPtrInit(&sBufPtr, psBuf); + + // + // Find the humidity value(main.humidity). + // + if(GetField("sys", &sBufPtr) != 0) + { + // + // Save the pointer to the data. + // + sBufMain = sBufPtr; + + // + // Get the sunrise time. + // + if(GetField("sunrise", &sBufPtr) != 0) + { + psWeatherReport->ui32SunRise = GetFieldValueInt(&sBufPtr); + + i32Items++; + } + else + { + psWeatherReport->ui32SunRise = 0; + } + + // + // Restore the pointer to the data. + // + sBufPtr = sBufMain; + + // + // Get the sunset time. + // + if(GetField("sunset", &sBufPtr) != 0) + { + psWeatherReport->ui32SunSet = GetFieldValueInt(&sBufPtr); + + i32Items++; + } + else + { + psWeatherReport->ui32SunSet = 0; + } + } + + // + // Reset the pointers. + // + BufPtrInit(&sBufPtr, psBuf); + + // + // Get the last update time. + // + if(GetField("dt", &sBufPtr) != 0) + { + psWeatherReport->ui32Time = GetFieldValueInt(&sBufPtr); + + i32Items++; + } + else + { + psWeatherReport->ui32Time = 0; + } + + // + // Reset the pointers. + // + BufPtrInit(&sBufPtr, psBuf); + + // + // Find the humidity value(main.humidity). + // + if(GetField("main", &sBufPtr) != 0) + { + // + // Save the pointer to the main data. + // + sBufMain = sBufPtr; + + if(GetField("humidity", &sBufPtr) != 0) + { + psWeatherReport->i32Humidity = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->i32Humidity = INVALID_INT; + } + + // + // Reset the buffer pointer to main. + // + sBufPtr = sBufMain; + + // + // Find the current temperature value. + // + if(GetField("temp", &sBufPtr) != 0) + { + psWeatherReport->i32Temp = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->i32Temp = INVALID_INT; + } + + // + // Reset the buffer pointer to main. + // + sBufPtr = sBufMain; + + // + // Find the current atmospheric pressure. + // + if(GetField("pressure", &sBufPtr) != 0) + { + psWeatherReport->i32Pressure = GetFieldValueInt(&sBufPtr); + i32Items++; + } + else + { + psWeatherReport->i32Pressure = INVALID_INT; + } + } + return(i32Items); +} -- cgit v1.3.1