Young.m. Choi

SunClock: Networks

Project Partner: Aidan Fowler
Github Repo:

System Diagram

As previously mentioned, this clock has four programs: a regular clock, blur clock, sun clock, and a movemotor. All of them is located in Raspberry pi, controlled by an app that is served using node and express.js.

Client Side

A server is on Raspberry pi: by running node server, user can access the app locally on port 8080 in the network.  

On the client side, a user will be asked to enter the zip code. That gets passed to the server via socket communication, then makes a http request to OpenCage API that returns  location data  and sun rise / sun set time.

Also, by using the app, the user can calibrate the motor to their preference and turn on / off Blur Clock and Sun Clock.

Server Side


io.on('connection', (socket) => {

    socket.on('getZipData', async (data) => {

    requestZip =;
    await makeSynchronouseRequest();

    dataOut = {
        sunRise : responseSunRise,
        sunSet : responseSunSet,
        city : cityInfo,


On the server side, when socket communication is connected, it asks for ‘zipdata’ from the client side, then makes a ‘synchronousRequest’, which includes callback for OpenCage API request.

When we get the data, then it “emits” back to the client side, showing the result on the app page.

At the same time, the data is used to control the sun’s location in the Sun Clock.

How Sunclock works

When server gets sun rise / set time, it passes data to program as a string. then takes the string, makes it as a time object using time module on python.

Then by converting the times to seconds, we can find out total sun light time, and where the sun is located at the moment, by using datetime module on python. The rest is a simple calculation and conversion to radian angle.

~ Code ~

#converting strings into sunrise time object
myString1 = sys.argv[1].replace('"','')
mySunRise = myString1.split(':')

tRh = int(mySunRise[0])
tRm = int(mySunRise[1])
tRs = int(mySunRise[2])
tR = dt.time(tRh, tRm, tRs)

#converting strings into sunset time object

myString2 = sys.argv[2].replace('"','')
mySunSet = myString2.split(':')

tSh = int(mySunSet[0])
tSm = int(mySunSet[1])
tSs = int(mySunSet[2])
tS = dt.time(tSh, tSm, tSs)
tN =

#sum of time
tRS = tR.hour * 3600 + tR.minute * 60 + tR.second
tSS = tS.hour * 3600 + tS.minute * 60 + tS.second
tNS = tN.hour * 3600 + tN.minute * 60 + tN.second

angle = -2.67794872
pi = 3.14159265
sunMoveRate = 2 * pi / 86400

totalSunTime = tSS - tRS
currnetSunTime = tNS - tRS
currentSunLoc = currnetSunTime / totalSunTime

#setting the center of rotation
cenX = 64 * 0.5
cenY = 32 * 1.5
sunRad = 8
sunPath = 35

totalSunPathAngle = 2.21429744
sunAngle = currentSunLoc * totalSunPathAngle