Subversion Repositories Kolibri OS

Rev

Rev 8553 | Rev 8555 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8553 superturbo 1
/* Copyright (C) 2019-2021 Logaev Maxim (turbocat2001), GPLv2 */
2
 
3
/*
4
    Info: App uses api from openweathermap.org.
5
    The standard configuration uses my token and the city of Moscow.
6
    You can always change it in the weather.json file.
7
    If you use UTF-8 encoding, then city names can be entered in different languages!
8
*/
9
 
10
#include 
11
#include 
12
#include "json/json.h"
13
#include 
14
#include 
15
#include 
16
#include 
17
 
8554 superturbo 18
#define VERSION  "Weather 1.2b"
8553 superturbo 19
 
20
enum BUTTONS{
21
    BTN_QUIT = 1,
22
    BTN_UPDATE = 2
23
};
24
 
25
#define JSON_OBJ(X) value->u.object.values[X]
26
#define OK 200
27
#define API       "http://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric"
28
#define IMAGE_URL "http://openweathermap.org/img/w/%s.png"
29
#define START_YPOS 34
8554 superturbo 30
#define UTF8_W 8
31
#define CP866_W 6
8553 superturbo 32
 
8554 superturbo 33
#define WINDOW_W 200
34
 
8553 superturbo 35
Image *image;
8554 superturbo 36
Image *blend;
37
 
38
char full_url[512];
8553 superturbo 39
char full_url_image[256];
40
struct kolibri_system_colors sys_color_table;
41
 
8554 superturbo 42
pos_t win_pos;
43
 
8553 superturbo 44
#pragma pack(push,1)
45
typedef struct {
8554 superturbo 46
    char City[256];
47
    int wind_speed;
8553 superturbo 48
    //int wind_deg;
49
    int pressure;
50
    int humidity;
8554 superturbo 51
    //char weath_main[256];
52
    char weath_desc[256];
8553 superturbo 53
    int visibility;
54
    int timezone;
8554 superturbo 55
    char image_code[4];
56
    int temp;
8553 superturbo 57
}open_weather_data;
58
#pragma pack(pop)
59
 
60
open_weather_data myw;
61
 
62
void notify_show(char *text)
63
{
64
   start_app("/sys/@notify", text);
65
}
66
 
67
void* safe_malloc(size_t size) // Безопасный malloc. Показывает уведомление об ошибке и закрывает программу если память не была выделена
68
{
69
    void *p=malloc(size);
70
    if(p==NULL){
71
       notify_show("'Memory allocation error!' -E");
72
       exit(0);
73
    }else{
74
        return p;
75
    }
76
}
77
 
8554 superturbo 78
 char tmp_buff[100];
79
 
8553 superturbo 80
static void draw_format_text_sys(int x, int y, color_t color, const char *format_str, ... )
81
{
82
    va_list ap;
83
    va_start (ap, format_str);
84
    vsnprintf(tmp_buff, sizeof tmp_buff ,format_str, ap);
85
    va_end(ap);
86
    draw_text_sys(tmp_buff, x, y , 0, color);
87
}
88
 
89
void find_and_set(json_value *value, open_weather_data* weather)
90
{
91
    for(int i=0; iu.object.length; i++){
92
        if(!strcmp(JSON_OBJ(i).name, "main")){
8554 superturbo 93
            if(JSON_OBJ(i).value->u.object.values[0].value->type==json_double)
94
            {
95
                weather->temp = (int)JSON_OBJ(i).value->u.object.values[0].value->u.dbl;
96
            }else{
97
                weather->temp = JSON_OBJ(i).value->u.object.values[0].value->u.integer;
98
            }
8553 superturbo 99
            weather->pressure = JSON_OBJ(i).value->u.object.values[4].value->u.integer;
100
            weather->humidity = JSON_OBJ(i).value->u.object.values[5].value->u.integer;
101
        }
102
        if(!strcmp(JSON_OBJ(i).name, "name")){
8554 superturbo 103
            strcpy(weather->City,JSON_OBJ(i).value->u.string.ptr);
8553 superturbo 104
        }
105
        if(!strcmp(JSON_OBJ(i).name, "weather")){
8554 superturbo 106
           strcpy(weather->weath_desc, JSON_OBJ(i).value->u.array.values[0]->u.object.values[2].value->u.string.ptr);
107
           strcpy(weather->image_code, JSON_OBJ(i).value->u.array.values[0]->u.object.values[3].value->u.string.ptr);
8553 superturbo 108
        }
109
        if(!strcmp(JSON_OBJ(i).name, "wind")){
8554 superturbo 110
            if(JSON_OBJ(i).value->u.object.values[0].value->type==json_double)
111
            {
112
                weather->wind_speed = (int)JSON_OBJ(i).value->u.object.values[0].value->u.dbl;
113
            }else{
114
                weather->wind_speed = JSON_OBJ(i).value->u.object.values[0].value->u.integer;
115
            }
8553 superturbo 116
        }
117
        if(!strcmp(JSON_OBJ(i).name, "visibility")){
118
            weather->visibility = JSON_OBJ(i).value->u.integer;
119
        }
120
        if(!strcmp(JSON_OBJ(i).name, "timezone")){
121
            weather->timezone = JSON_OBJ(i).value->u.integer/60/60;
122
        }
123
        if(!strcmp(JSON_OBJ(i).name, "message")){
124
            char *errmsg = safe_malloc(weather->timezone = JSON_OBJ(i).value->u.string.length+6);
125
            sprintf(errmsg,"'%s!' -E", JSON_OBJ(i).value->u.string.ptr);
126
            notify_show(errmsg);
8554 superturbo 127
            free(errmsg);
8553 superturbo 128
        }
129
    }
130
}
131
 
132
http_msg* get_json(char *City, char *Token)
133
{
134
    sprintf(full_url, API, City, Token);
135
    http_msg *h = http_get(full_url, 0,  HTTP_FLAG_BLOCK, "");
136
    http_long_receive(h);
137
    if (h->status == OK || h->status == 404) {
8554 superturbo 138
        return h;
8553 superturbo 139
    } else {
140
        return NULL;
141
    }
142
}
143
 
144
void get_image(){
145
    sprintf(full_url_image, IMAGE_URL, myw.image_code);
146
    http_msg *h= http_get(full_url_image, 0,  HTTP_FLAG_BLOCK, "");
147
    http_long_receive(h);
148
 
149
    if (h->status == OK) {
150
        image = img_decode(h->content_ptr, h->content_length, 0); // Decode RAW data to Image data
151
        if (image->Type != IMAGE_BPP32) {
152
            image = img_convert(image, NULL, IMAGE_BPP32, 0, 0); // Convert image to format BPP32
153
                if (!image) {
154
                notify_show("'Convetring image error!' -E");
155
                exit(0);
156
            }
157
        }
8554 superturbo 158
        user_free(h->content_ptr);
159
        user_free(h);
160
        blend = img_create(64, 64, IMAGE_BPP32);  // Create an empty layer
161
        img_fill_color(blend, 64, 64, sys_color_table.work_area); // Fill the layer with one color
162
        Image* image2 = img_scale(image, 0, 0, 50, 50, NULL, LIBIMG_SCALE_STRETCH , LIBIMG_INTER_BILINEAR, 64, 64);
163
        img_blend(blend, image2, 0, 0, 0, 0, 64, 64);  // Blending images to display the alpha channel.
164
        img_destroy(image);
165
        img_destroy(image2);
8553 superturbo 166
    }else{
167
       notify_show("'Image not loaded!!' -W");
168
    }
169
}
170
 
171
void RedrawGUI() //Рисуем окно
172
{
173
    begin_draw(); //Начинаем рисование интерфейса )
8554 superturbo 174
 
175
    int new_win_w = (strlen(myw.City)+11)*UTF8_W;
176
    if(new_win_w
177
        new_win_w=WINDOW_W;
178
    }
179
 
180
    sys_create_window(win_pos.x, win_pos.y, new_win_w, START_YPOS+200, VERSION, sys_color_table.work_area, 0x14); // Создаём окно.
8553 superturbo 181
 
8554 superturbo 182
    draw_format_text_sys(20, START_YPOS, 0xB0000000 | sys_color_table.work_text, "%s (UTC%+d)", myw.City, myw.timezone);
183
    draw_format_text_sys(21, START_YPOS, 0xB0000000 | sys_color_table.work_text, "%s (UTC%+d)", myw.City, myw.timezone);
8553 superturbo 184
 
8554 superturbo 185
    img_draw(blend, 10, START_YPOS+30, 64,64,0,0);
8553 superturbo 186
 
8554 superturbo 187
    draw_format_text_sys(20, START_YPOS+20, 0xb0000000 | sys_color_table.work_text, myw.weath_desc);
188
    draw_format_text_sys(21, START_YPOS+20, 0xb0000000 | sys_color_table.work_text, myw.weath_desc);
8553 superturbo 189
 
8554 superturbo 190
    draw_format_text_sys(100, START_YPOS+45, 0xB1000000 | sys_color_table.work_text, "%+d°C", myw.temp);
191
    draw_format_text_sys(101, START_YPOS+46, 0xB1000000 | sys_color_table.work_text, "%+d°C", myw.temp);
8553 superturbo 192
 
8554 superturbo 193
    draw_format_text_sys(20, START_YPOS+80, 0x90000000 | sys_color_table.work_text,  "Pressure:   %d hPa",myw.pressure);
194
    draw_format_text_sys(20, START_YPOS+100, 0x90000000 | sys_color_table.work_text, "Humidity:   %d %s", myw.humidity, "%");
195
    draw_format_text_sys(20, START_YPOS+120, 0x90000000 | sys_color_table.work_text, "Wind speed: %d m/s", myw.wind_speed);
196
    draw_format_text_sys(20, START_YPOS+140, 0x90000000 | sys_color_table.work_text, "Visibility: %d m", myw.visibility);
8553 superturbo 197
 
8554 superturbo 198
    define_button(X_W(new_win_w/2-40,80), Y_H(START_YPOS+160,30), BTN_UPDATE, sys_color_table.work_button);
199
    draw_text_sys("Update", (new_win_w/2)-(CP866_W*4), START_YPOS+170, 0, 0x90000000 | sys_color_table.work_button_text);
8553 superturbo 200
    end_draw();
201
}
202
 
203
void get_config(char **City, char **Token)
204
{
205
    FILE *config_j = fopen("weather.json", "rb");
206
    if(config_j==NULL){
207
        notify_show("'Configuration file not found!' -E");
208
        exit(0);
209
    }
210
    size_t size = _ksys_get_filesize("weather.json");
211
    char *config_buff = safe_malloc(size+1);
212
    if(size != fread(config_buff, sizeof(char), size, config_j)){
213
        notify_show("'The configuration file was not fully read!' -E");
214
        exit(0);
215
    }
216
    json_value* value =json_parse (config_buff, size);
217
    for(int i=0; iu.object.length; i++){
218
        if(!strcmp(JSON_OBJ(i).name, "Location")){
219
          *City = JSON_OBJ(i).value->u.string.ptr;
220
        }
221
        if(!strcmp(JSON_OBJ(i).name, "Token")){
222
           *Token = JSON_OBJ(i).value->u.string.ptr;
223
        }
224
    }
225
    if(*City==NULL || *Token ==NULL){
226
         notify_show("'Invalid config!!' -E");
227
         exit(0);
228
    }
229
    free(config_buff);
8554 superturbo 230
    fclose(config_j);
8553 superturbo 231
}
232
 
233
void Update(char* city, char* token)
234
{
8554 superturbo 235
    if(blend!=NULL){
236
        img_destroy(blend);
237
    }
8553 superturbo 238
    memset(&myw, 0, sizeof myw);
8554 superturbo 239
    strcpy(myw.City,"None");
240
    strcpy(myw.weath_desc,"unknown");
8553 superturbo 241
    http_msg *json_file = get_json(city, token);
242
    if(json_file != NULL){
8554 superturbo 243
        json_value* value=json_parse (json_file->content_ptr, json_file->content_length);
8553 superturbo 244
        find_and_set(value, &myw);
245
        get_image();
8554 superturbo 246
        json_value_free(value);
247
        user_free(json_file->content_ptr);
248
        user_free(json_file);
249
 
8553 superturbo 250
    }else{
8554 superturbo 251
       notify_show("'Connection error!' -E");
8553 superturbo 252
    }
253
}
254
 
255
int main(){
8554 superturbo 256
    win_pos = get_mouse_pos(0);
257
    if(!kolibri_libimg_init()){
258
        notify_show("Libimg.obj not loaded!' -E");
259
        exit(0);
260
    }
8553 superturbo 261
    get_system_colors(&sys_color_table);
262
    char *City = NULL;
263
    char *Token = NULL;
264
    get_config(&City, &Token);
265
    Update(City,Token);
8554 superturbo 266
 
8553 superturbo 267
    while(1){
268
        switch(get_os_event()){
269
            case KOLIBRI_EVENT_NONE:
270
                break;
271
            case KOLIBRI_EVENT_REDRAW:
272
                RedrawGUI();
273
                break;
274
            case KOLIBRI_EVENT_BUTTON: // Событие обработки кнопок
275
                switch (get_os_button()){
276
                    case BTN_UPDATE:
277
                        Update(City, Token);
278
                        RedrawGUI();
279
                        break;
280
                    case BTN_QUIT:
281
                        exit(0);
282
                        break;
283
                }
284
        }
285
    }
286
    return 0;
287
}