Dinfio Playground

Let's play with Dinfio!




Clock Widget using Raspberry Pi + Dinfio

This is fun and great project using Raspberry Pi and Dinfio. Let's build DIY analogue clock featured the following widgets:



The prayer times widget grabs data from aladhan.com API (International) and myQuran.com API (Kemenag RI, this is for Indonesia only). And the weather widget grabs data from OpenWeather API.

What stuff we need?

In this project, we will need: Let's get started!

Download the project here and extract it to your home directory or somewhere else. You will get clock.fio file and weather_icons directory. Open Terminal and run the project:
$ dinfio clock.fio

That's all! You will see beautiful Clock Widget appears on your LCD!

Updated:
Source Code:

' Clock with prayer times and weather widgets using Dinfio
 
import time
import gui, math, string
import url, json
import fileio
 
var name = "Your name"
var city = "Depok"
var country = "Indonesia"
var kemenag_city = "1225"   ' Depok, ID. Please see https://bit.ly/API-myQuran-v2
var latitude = -6.3658284
var longitude = 106.8163953
var api_key = "Your OpenWeather API Key"
 
var current_day = get_day()
var current_hour = get_hour()
var current_minute = -1
var panel_index = 0
var total_panels = 4
 
var width = 200, height = 200
var window_width = width + 256
var window_height = height + 128
var center_x = width / 2, center_y = height / 2
var radius = center_x
 
var colour_window = colour.hex("10061c")
var colour_line = colour.hex("404040")
var colour_line_alt = colour.hex("404040")
var colour_back = colour.hex("c0c0c0")
var colour_title = colour.hex("a0a0a0")
var colour_label = colour.hex("a0a0a0")
var colour_weather = colour.hex("e0e0e0")
 
var dir = getfoldername(getcurrentfile())
 
var prayer_times = [
    ["Fajr", "", 0],
    ["Dhuhr", "", 0],
    ["Asr", "", 0],
    ["Maghrib", "", 0],
    ["Isha", "", 0]
]
 
 
' Weather data will not be updated in this hours for the energy saver
 
var sleep_hours = [
    22, 23, 0, 1, 2, 3, 4
]
 
var weather_request = {
    lat: latitude,
    lon: longitude,
    units: "metric",
    exclude: "minutely,daily",
    appid: api_key
}
 
start
    window = gui_window("Clock + Prayer Times", window_width, window_height)
    canvas = gui_panel(window, 20, 78, width + 5, height + 5, true)
    label_title = gui_label("Clock Widget using Dinfio", window, 20, 14)
    timer = gui_timer(1000, draw())
 
 
    ' This is using Kemenag RI (Indonesia only) API,
    ' use load_prayertimes() if you want to connect to international aladhan.com API instead
 
    timer_load = gui_timer(1000, load_prayertimes_kemenag_ri())
    timer_load_weather = gui_timer(2000, load_weather())
 
    panel = []
    panel[0] = gui_panel(window, 250, 68, window_width, window_height)
    panel[1] = gui_panel(window, 250, 68, window_width, window_height)
    panel[2] = gui_panel(window, 250, 68, window_width, window_height)
    panel[3] = gui_panel(window, 250, 68, window_width, window_height)
 
    left = 0
    top = 0
    margin = 28
    margin_alt = 52
 
 
    ' Prayer times
 
    label_closest = gui_label("Getting data...", panel[0], left, top)
 
    label_header_fajr = gui_label("", panel[0], left, label_closest.gety() + margin_alt)
    label_header_dhuhr = gui_label("", panel[0], left, label_header_fajr.gety() + margin)
    label_header_asr = gui_label("", panel[0], left, label_header_dhuhr.gety() + margin)
    label_header_maghrib = gui_label("", panel[0], left, label_header_asr.gety() + margin)
    label_header_isha = gui_label("", panel[0], left, label_header_maghrib.gety() + margin)
 
    label_fajr = gui_label("", panel[0], left + 100, label_closest.gety() + margin_alt)
    label_dhuhr = gui_label("", panel[0], left + 100, label_header_fajr.gety() + margin)
    label_asr = gui_label("", panel[0], left + 100, label_header_dhuhr.gety() + margin)
    label_maghrib = gui_label("", panel[0], left + 100, label_header_asr.gety() + margin)
    label_isha = gui_label("", panel[0], left + 100, label_header_maghrib.gety() + margin)
 
    label_temp = gui_label("", panel[0], left, label_header_isha.gety() + margin + 20)
 
 
    ' Weather
 
    label_weather = gui_label("Getting data...", panel[1], left, top + 94)
    image_weather = gui_imagebox(dir & "/weather_icons/01d.png", panel[1], left, top)
    label_weather_detail = gui_label("", panel[1], left, top + 140, 180, 120)
 
 
    ' Hourly forecast
 
    label_hourly_title1 = gui_label("Hourly Forecast", panel[2], left, top)
    label_hourly_title2 = gui_label("Hourly Forecast", panel[3], left, top)
    label_hourly1 = gui_label("", panel[2], left, label_hourly_title1.gety() + margin_alt, 180, 300)
    label_hourly2 = gui_label("", panel[3], left, label_hourly_title2.gety() + margin_alt, 180, 300)
 
 
    ' Styles
 
    window.setbackgroundcolour(colour_window)
    canvas.setbackgroundcolour(colour_window)
    panel[0].setbackgroundcolour(colour_window)
    panel[1].setbackgroundcolour(colour_window)
    panel[2].setbackgroundcolour(colour_window)
    panel[3].setbackgroundcolour(colour_window)
 
    panel[0].setvisible(false)
    panel[1].setvisible(true)
    panel[2].setvisible(false)
    panel[3].setvisible(false)
 
    label_title.setfontsize(20)
    label_title.setfontbold(true)
    label_title.setforegroundcolour(colour_weather)
 
    label_closest.setfontsize(18)
    label_closest.setfontbold(true)
    label_closest.setforegroundcolour(colour_weather)
 
    label_header_fajr.setfontsize(14)
    label_header_dhuhr.setfontsize(14)
    label_header_asr.setfontsize(14)
    label_header_maghrib.setfontsize(14)
    label_header_isha.setfontsize(14)
 
    label_fajr.setfontsize(14)
    label_dhuhr.setfontsize(14)
    label_asr.setfontsize(14)
    label_maghrib.setfontsize(14)
    label_isha.setfontsize(14)
 
    label_header_fajr.setforegroundcolour(colour_label)
    label_header_dhuhr.setforegroundcolour(colour_label)
    label_header_asr.setforegroundcolour(colour_label)
    label_header_maghrib.setforegroundcolour(colour_label)
    label_header_isha.setforegroundcolour(colour_label)
 
    label_fajr.setforegroundcolour(colour_label)
    label_dhuhr.setforegroundcolour(colour_label)
    label_asr.setforegroundcolour(colour_label)
    label_maghrib.setforegroundcolour(colour_label)
    label_isha.setforegroundcolour(colour_label)
 
    label_temp.setfontsize(10)
    label_temp.setforegroundcolour(colour_label)
 
    label_weather.setfontsize(18)
    label_weather.setfontbold(true)
    label_weather.setforegroundcolour(colour_weather)
 
    label_weather_detail.setfontsize(14)
    label_weather_detail.setforegroundcolour(colour_label)
 
    label_hourly_title1.setfontsize(18)
    label_hourly_title1.setfontbold(true)
    label_hourly_title1.setforegroundcolour(colour_weather)
    label_hourly_title2.setfontsize(18)
    label_hourly_title2.setfontbold(true)
    label_hourly_title2.setforegroundcolour(colour_weather)
 
    label_hourly1.setfontsize(14)
    label_hourly1.setforegroundcolour(colour_label)
    label_hourly2.setfontsize(14)
    label_hourly2.setforegroundcolour(colour_label)
 
    window.addevent(event.mouseleftdown, toggle_fullscreen())
    window.setfullscreen(true)
    window.show()
 
    timer.run()
    timer_load.run()
    timer_load_weather.run()
 
    if !in_sleep_hours()
        label_title.settext(datetime("%A, %e %B %Y"))
        toggle_widget_enable = true
    else
        label_title.settext("Good night, " & name & ".")
        toggle_widget_enable = false
 
        panel[0].setvisible(true)
        panel[1].setvisible(false)
        panel[2].setvisible(false)
        panel[3].setvisible(false)
    endif
 
    draw()
stop
 
function draw()
    seconds = get_second() * 6 - 90
    minutes = (get_minute() + get_second() / 60) * 6 - 90
    hours = (get_hour() + get_minute() / 60) * 30 - 90
 
    canvas.draw_clear()
 
    canvas.draw_setpen(colour_line_alt, 0)
    canvas.draw_setbrush(colour_back)
    canvas.draw_circle(center_x, center_y, radius)
 
    canvas.draw_setpen(colour_line, 0)
    canvas.draw_setbrush(colour_line)
    canvas.draw_circle(center_x, center_y, 7)
 
    for i, 30, 360, 30
        if i != 360 && i != 90 && i != 180 && i != 270
            canvas.draw_circle((radius - 20) * cosd(i) + center_x, (radius - 20) * sind(i) + center_y, 2)
        endif
    endfor
 
    canvas.draw_setpen(colour_line, 6)
    canvas.draw_line(center_x, center_y, (radius - 48) * cosd(hours) + center_x, (radius - 48) * sind(hours) + center_y)
    canvas.draw_setpen(colour_line, 4)
    canvas.draw_line(center_x, center_y, (radius - 24) * cosd(minutes) + center_x, (radius - 24) * sind(minutes) + center_y)
    canvas.draw_setpen(colour_line, 2)
    canvas.draw_line(center_x, center_y, (radius - 20) * cosd(seconds) + center_x, (radius - 20) * sind(seconds) + center_y)
    canvas.draw_line(center_x, center_y, 18 * -cosd(seconds) + center_x, 18 * -sind(seconds) + center_y)
 
    canvas.draw_settextcolour(colour_line)
    canvas.draw_setfont(14)
    canvas.draw_text("12", (radius - 20) * cosd(-90) + center_x - 10, (radius - 20) * sind(-90) + center_y - 10)
    canvas.draw_text("6", (radius - 20) * cosd(90) + center_x - 5, (radius - 20) * sind(90) + center_y - 10)
    canvas.draw_text("3", (radius - 20) * cosd(0) + center_x - 5, (radius - 20) * sind(0) + center_y - 10)
    canvas.draw_text("9", (radius - 20) * cosd(180) + center_x - 5, (radius - 20) * sind(180) + center_y - 10)
 
    canvas.refresh()
    calculate_closest()
stop
 
function load_prayertimes_kemenag_ri()
    timer_load.pause()
 
    date = datetime("%Y/%m/%d")
    response = url.get("https://api.myquran.com/v2/sholat/jadwal/" & kemenag_city & "/" & date)
 
    if response.code == 200
        data = json.decode(response.body)
 
        if data.status == true
            timings = data.data.jadwal
 
            prayer_times[0][1] = timings.subuh
            prayer_times[1][1] = timings.dzuhur
            prayer_times[2][1] = timings.ashar
            prayer_times[3][1] = timings.maghrib
            prayer_times[4][1] = timings.isya
 
            prayer_times[0][2] = getnumber(replace(timings.subuh, ":", ""))
            prayer_times[1][2] = getnumber(replace(timings.dzuhur, ":", ""))
            prayer_times[2][2] = getnumber(replace(timings.ashar, ":", ""))
            prayer_times[3][2] = getnumber(replace(timings.maghrib, ":", ""))
            prayer_times[4][2] = getnumber(replace(timings.isya, ":", ""))
 
            label_header_fajr.settext("Fajr:")
            label_header_dhuhr.settext("Dhuhr:")
            label_header_asr.settext("Asr:")
            label_header_maghrib.settext("Maghrib:")
            label_header_isha.settext("Isha:")
 
            label_fajr.settext(prayer_times[0][1])
            label_dhuhr.settext(prayer_times[1][1])
            label_asr.settext(prayer_times[2][1])
            label_maghrib.settext(prayer_times[3][1])
            label_isha.settext(prayer_times[4][1])
 
            calculate_closest()
        else
            label_closest.settext("API Error")
        endif
    elseif response.code != 0
        label_closest.settext("Error: HTTP " & response.code)
    else
        label_closest.settext(response.error_string)
    endif
stop
 
function load_prayertimes()
    timer_load.pause()
 
    request = {
        city: city,
        country: country,
        method: 4   ' Umm al-Qura University, Makkah
    }
 
    response = url.get("https://api.aladhan.com/v1/timingsByCity", request)
 
    if response.code == 200
        data = json.decode(response.body)
        timings = data.data.timings
 
        prayer_times[0][1] = timings.fajr
        prayer_times[1][1] = timings.dhuhr
        prayer_times[2][1] = timings.asr
        prayer_times[3][1] = timings.maghrib
        prayer_times[4][1] = timings.isha
 
        prayer_times[0][2] = getnumber(replace(timings.fajr, ":", ""))
        prayer_times[1][2] = getnumber(replace(timings.dhuhr, ":", ""))
        prayer_times[2][2] = getnumber(replace(timings.asr, ":", ""))
        prayer_times[3][2] = getnumber(replace(timings.maghrib, ":", ""))
        prayer_times[4][2] = getnumber(replace(timings.isha, ":", ""))
 
        label_header_fajr.settext("Fajr:")
        label_header_dhuhr.settext("Dhuhr:")
        label_header_asr.settext("Asr:")
        label_header_maghrib.settext("Maghrib:")
        label_header_isha.settext("Isha:")
 
        label_fajr.settext(prayer_times[0][1])
        label_dhuhr.settext(prayer_times[1][1])
        label_asr.settext(prayer_times[2][1])
        label_maghrib.settext(prayer_times[3][1])
        label_isha.settext(prayer_times[4][1])
 
        calculate_closest()
    elseif response.code != 0
        label_closest.settext("Error: HTTP " & response.code)
    else
        label_closest.settext(response.error_string)
    endif
stop
 
function load_weather()
    timer_load_weather.pause()
    response = url.get("https://api.openweathermap.org/data/2.5/onecall", weather_request)
 
    if response.code == 200
        data = json.decode(response.body)
 
        temperature = round(data.current.temp, 0) & "°C"
        description = data.current.weather[0].description
        description = ucase(substring(description, 0, 1)) & substring(description, 1)
        icon = data.current.weather[0].icon
 
        label_weather.settext(data.current.weather[0].main & " / " & temperature)
        label_weather_detail.settext(description & "\n" & city)
        image_weather.setimage(dir & "/weather_icons/" & icon & ".png")
 
 
        ' Hourly forecast
 
        hourly = data.hourly
        hourly1 = ""
        hourly2 = ""
 
        for i, 0, 5
            hour = datetime("%H:00", hourly[i].dt)
            pop = round(hourly[i].pop * 100) & "%"
 
            hourly1 = hourly1 & hour & "    " & hourly[i].weather[0].main & " " & pop & "\n"
        endfor
 
        for i, 6, 11
            hour = datetime("%H:00", hourly[i].dt)
            pop = round(hourly[i].pop * 100) & "%"
 
            hourly2 = hourly2 & hour & "    " & hourly[i].weather[0].main & " " & pop & "\n"
        endfor
 
        label_hourly1.settext(hourly1)
        label_hourly2.settext(hourly2)
    elseif response.code != 0
        label_weather.settext("Error: HTTP " & response.code)
    else
        label_weather.settext(response.error_string)
    endif
stop
 
function calculate_closest()
    if prayer_times[0][1] != ""
        closest = inf
        index = 0
 
        hour = get_hour()
        minute = get_minute()
        minute = iif(minute < 10, "0" & minute, minute)
 
        for i, 0, 4
            dist = prayer_times[i][2] - getnumber(hour & minute)
 
            if dist < closest && dist >= 0
                closest = dist
                index = i
            endif
        endfor
 
        label_closest.settext(prayer_times[index][0] & ":   " & prayer_times[index][1])
    endif
 
    if get_day() != current_day
        current_day = get_day()
 
        label_closest.settext("Getting data...")
        timer_load.run()
    endif
 
    if get_hour() != current_hour
        current_hour = get_hour()
 
        if !in_sleep_hours()
            label_title.settext(datetime("%A, %e %B %Y"))
            toggle_widget_enable = true
 
            label_weather.settext("Getting data...")
            timer_load_weather.run()
        else
            label_title.settext("Good night, " & name & ".")
            toggle_widget_enable = false
 
            panel[0].setvisible(true)
            panel[1].setvisible(false)
            panel[2].setvisible(false)
            panel[3].setvisible(false)
        endif
    endif
 
    if get_minute() != current_minute
        current_minute = get_minute()
        label_temp.settext("CPU Temp: " & get_temperature() & "°C")
    endif
 
    if toggle_widget_enable
        if get_second() % 10 == 0
            toggle_widget()
        endif
    endif
stop
 
function in_sleep_hours()
    hour = get_hour()
    yield false
 
    for i, 0, size(sleep_hours) - 1
        if hour == sleep_hours[i]
            return true
        endif
    endfor
stop
 
function get_temperature()
    return round(getnumber(filecontent("/sys/class/thermal/thermal_zone0/temp")) / 1000, 1)
stop
 
function toggle_widget()
    for i, 0, total_panels - 1
        panel[i].setvisible(false)
    endfor
 
    panel_index += 1
    if panel_index >= total_panels; panel_index = 0; endif
 
    panel[panel_index].setvisible(true)
stop
 
function toggle_fullscreen()
    window.setfullscreen(!window.isfullscreen())
stop


← Back to the Dinfio Playground / Posted on: 5 June 2021. Updated on: 12 June 2021