This project allows to check temperature at home from anywhere using web browser

I made a similar project using Arduino here https://www.hackster.io/khanhhs/ardu...mometer-a38752


Demo




Things Used In This Project
  • PHPoC Blue (We can use PHPoC Black if using Ethernet instead of WiFi)
  • Waterproof DS18B20 Digital temperature sensor
  • Resistor 4.7k ohm


Wiring Diagram

Click image for larger version  Name:	PHPoC_Thermometer_wiring1.png Views:	1 Size:	136.8 KB ID:	722

Or


Click image for larger version  Name:	PHPoC_Thermometer_wiring_2.JPG Views:	1 Size:	33.3 KB ID:	723

Click image for larger version  Name:	PHPoC_Thermometer_connect.jpg Views:	1 Size:	45.7 KB ID:	724



Data Flow

PHPoC ---> Web browser

PHPoC reads temperature from sensor and send it to Web Browser via websocket. JavaScript function visualizes the temperature value on UI.



Source Code

Source code includes two files:
- index.php: This file is client side code. When receiving HTTP request from web browser, PHPoC interprets PHP script in this file, and then send the interpreted file to web browser. The interpreted file (contains html, css and JavaScript code) provides UI (User Interface), visualizing temperature received from PHPoC.
PHP Code:
<!DOCTYPE html>
<html>
<head>
<title>PHPoC - Thermometer</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<meta charset="utf-8">
<style>
body { text-align: center; font-size: width/2pt; }
h1 { font-weight: bold; font-size: width/2pt; }
h2 { font-weight: bold; font-size: width/2pt; }
button { font-weight: bold; font-size: width/2pt; }
</style>
<script>
var canvas_width = 200, canvas_height = 450;

var ws;
var buffer = "";

function init()
{
    var canvas = document.getElementById("remote");
    //canvas.style.backgroundColor = "#999999";
    canvas.width = canvas_width;
    canvas.height = canvas_height;

    var ctx = canvas.getContext("2d");

    ctx.translate(canvas_width/2, canvas_height - 80);

    update_view(0);
}
function connect_onclick()
{
    if(ws == null)
    {
        var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
        if((navigator.platform.indexOf("Win") != -1) && (ws_host_addr.charAt(0) == "["))
        {
            // network resource identifier to UNC path name conversion
            ws_host_addr = ws_host_addr.replace(/[\[\]]/g, '');
            ws_host_addr = ws_host_addr.replace(/:/g, "-");
            ws_host_addr += ".ipv6-literal.net";
        }

        ws = new WebSocket("ws://" + ws_host_addr + "/thermometer", "text.phpoc");
        document.getElementById("ws_state").innerHTML = "CONNECTING";
        ws.onopen = ws_onopen;
        ws.onclose = ws_onclose;
        ws.onmessage = ws_onmessage;
        //ws.binaryType = "arraybuffer";
    }
    else
        ws.close();
}
function ws_onopen()
{
    document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>";
    document.getElementById("bt_connect").innerHTML = "Disconnect";
    ws.send("wsm_baud=9600\r\n");
    ws.send("B\r\n");
    update_view(0);
}
function ws_onclose()
{
    document.getElementById("ws_state").innerHTML = "<font color='gray'>CLOSED</font>";
    document.getElementById("bt_connect").innerHTML = "Connect";
    ws.onopen = null;
    ws.onclose = null;
    ws.onmessage = null;
    ws = null;
    update_view(0);
}
function ws_onmessage(e_msg)
{
    e_msg = e_msg || window.event; // MessageEvent

    console.log(e_msg.data);

    update_view(parseFloat(e_msg.data));
}
function update_view(temp)
{
    var canvas = document.getElementById("remote");
    var ctx = canvas.getContext("2d");

    var radius = 70;
    var offset = 5;
    var width = 45;
    var height = 330;

    ctx.clearRect(-canvas_width/2, -350, canvas_width, canvas_height);

    if(ws != null)
    {
        ctx.strokeStyle="blue";
        ctx.fillStyle="blue";
    }
    else
    {
        ctx.strokeStyle="Gray";
        ctx.fillStyle="Gray";
    }

    //5-step Degree
    var x = -width/2;
    ctx.lineWidth=2;
    for (var i = 0; i <= 100; i+=5)
    {
        var y = -(height - radius)*i/100 - radius - 5;
        ctx.beginPath();
        ctx.lineTo(x, y);
        ctx.lineTo(x - 20, y);
        ctx.stroke();
    }

    //20-step Degree
    ctx.lineWidth=5;
    for (var i = 0; i <= 100; i+=20)
    {
        var y = -(height - radius)*i/100 - radius - 5;
        ctx.beginPath();
        ctx.lineTo(x, y);
        ctx.lineTo(x - 25, y);
        ctx.stroke();

        ctx.font="20px Georgia";
        ctx.textBaseline="middle";
        ctx.textAlign="right";
        ctx.fillText(i.toString(), x - 35, y);
    }

    // shape
    ctx.lineWidth=16;
    ctx.beginPath();
    ctx.arc(0, 0, radius, 0, 2 * Math.PI);
    ctx.stroke();

    ctx.beginPath();
    ctx.rect(-width/2, -height, width, height);
    ctx.stroke();

    ctx.beginPath();
    ctx.arc(0, -height, width/2, 0, 2 * Math.PI);
    ctx.stroke();

    ctx.fillStyle="#e6e6ff";
    ctx.beginPath();
    ctx.arc(0, 0, radius, 0, 2 * Math.PI);
    ctx.fill();

    ctx.beginPath();
    ctx.rect(-width/2, -height, width, height);
    ctx.fill();

    ctx.beginPath();
    ctx.arc(0, -height, width/2, 0, 2 * Math.PI);
    ctx.fill();

    // temperature value
    if(ws != null)
        ctx.fillStyle="#ff1a1a";
    else
        ctx.fillStyle="Gray";

    ctx.beginPath();
    ctx.arc(0, 0, radius - offset, 0, 2 * Math.PI);
    ctx.fill();

    temp = Math.round(temp);
    var y = (height - radius)*temp/100.0 + radius + 5;
    ctx.beginPath();
    ctx.rect(-width/2 + offset, -y, width - 2*offset, y);
    ctx.fill();

    if(ws != null)
    {
        ctx.fillStyle="white";
        ctx.font="bold 34px Georgia";
        ctx.textBaseline="middle";
        ctx.textAlign="center";
        ctx.fillText(temp.toString() + "°C", 0, 0);
    }
}

window.onload = init;
</script>
</head>

<body>

<p>
<h1>PHPoC - Web Thermometer</h1>
</p>

<canvas id="remote"></canvas>

<h2>
<p>
WebSocket : <span id="ws_state">null</span>
</p>
<button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button>
</h2>

</body>
</html>



- task0.php: This file is server side code. It is run in infinite loop to read temperature from sensor and send it to web browser via websoket
PHP Code:
<?php
include_once "/lib/sd_340.php";
include_once 
"/lib/sn_tcp_ws.php";

//bus reset
function begin()
{
    global 
$pid_ht_in$pid_ht_out;

    
pid_ioctl($pid_ht_in"set repc 4");
    
pid_ioctl($pid_ht_in"start");

    
pid_ioctl($pid_ht_out"set count 1 600");
    
pid_ioctl($pid_ht_out"set repc 2");
    
pid_ioctl($pid_ht_out"start");
    while(
pid_ioctl($pid_ht_out"get state"))
        ;
    
pid_ioctl($pid_ht_out"stop");

    while(
pid_ioctl($pid_ht_in"get state"))
        ;
    
pid_ioctl($pid_ht_in"stop");

    
$presence_pulse pid_ioctl($pid_ht_in"get count 3");
    if((
$presence_pulse 60) || ($presence_pulse 240))
        return 
false;
    else
        return 
true;
}

//1byte send
function write_byte($seq_str)
{
    global 
$pid_ht_out;
    
pid_ioctl($pid_ht_out"set count $seq_str");

    
pid_ioctl($pid_ht_out"set repc 16");
    
pid_ioctl($pid_ht_out"start");
    while(
pid_ioctl($pid_ht_out"get state"))
        ;
    
pid_ioctl($pid_ht_out"stop");
}

//1byte recieve
function read_byte()
{
    global 
$pid_ht_out$pid_ht_in;
    
$seq_read "1 3 63 3 63 3 63 3 63 3 63 3 63 3 63 3";
    
$sum 0;
    
$value 0;


    
pid_ioctl($pid_ht_in"set repc 16");
    
pid_ioctl($pid_ht_in"start");

    
pid_ioctl($pid_ht_out"set count $seq_read");
    
pid_ioctl($pid_ht_out"set repc 16");
    
pid_ioctl($pid_ht_out"start");
    while(
pid_ioctl($pid_ht_out"get state"))
        ;
    
pid_ioctl($pid_ht_out"stop");

    while(
pid_ioctl($pid_ht_in"get state"))
        ;
    
pid_ioctl($pid_ht_in"stop");

    for(
$i 0$i 8$i++)
    {
        
$cnt $i 1;
        
$cnt_val pid_ioctl($pid_ht_in"get count $cnt");
        if(
$cnt_val 15)
            
$value 1;
        else
            
$value 0;

        
$value <<= $i;
        
$sum += $value;
    }

    return 
$sum;
}

//SKIP ROM command
function skip_rom()
{
    global 
$seq_skip_rom;
    
write_byte($seq_skip_rom);
}

//CONVERT T command
function convert_t()
{
    global 
$seq_convert_t;

    
begin();
    
skip_rom();

    
write_byte($seq_convert_t);
    
usleep(750000);
}

//READ SCRATCHPAD
function read_scratchpad()
{
    global 
$seq_read_scratchpad;
    
$str "";

    
write_byte($seq_read_scratchpad);

    for(
$i 0$i 9$i++)
    {
        
$data read_byte();
        
$str .= int2bin($data1);
        if(
$i == 8)
            
$crc_scratchpad $data;
    }    

    
$crc = (int)system("crc 8 %1 00 8c lsb"substr($str0, -1));
    if(
$crc != $crc_scratchpad)
    {
        echo 
"CRC Error!\r\n";
        return 
false;
    }
    else
        return 
$str;
}

//read temperature
function read_temp()
{
    
begin();
    
skip_rom();

    
$scratchpad_data read_scratchpad();
    if(
$scratchpad_data === false)
        return 
false;

    
$temp bin2int(substr($scratchpad_data02), 02);

    
$temp_int $temp >> 4;
    
$temp_dec 0;
    
$dec_flag 0;

    for(
$i 0$i 4$i++)
    {
        if(
$temp 0x01)
        {
            
$dec_flag 1;
            
$temp_dec += 1.0 pow(2, (4-$i));
        }
        
$temp >>= 1;
    }

    if(
$dec_flag)
    {
        
$temp_tot $temp_int $temp_dec;
        return (float) 
$temp_tot;
    }
    else
        return (float) 
$temp_int;
}

//timing
$seq_skip_rom        "1 65 5 65 5 10 55 10 55 65 5 65 5 10 55 10";   // 0xcc
$seq_convert_t       "1 65 5 65 5 10 55 65 5 65 5 65 5 10 55 65";    // 0x44
$seq_read_scratchpad "1 65 5 10 55 10 55 10 55 10 55 10 55 65 5 10"// 0xbe

//init HT1
$pid_ht_in pid_open("/mmap/ht1");
pid_ioctl($pid_ht_in"set div us");
pid_ioctl($pid_ht_in"set mode capture toggle");
pid_ioctl($pid_ht_in"set trigger from pin fall");

//init HT0
$pid_ht_out pid_open("/mmap/ht0");
pid_ioctl($pid_ht_out"set div us");
pid_ioctl($pid_ht_out"set mode output toggle");
pid_ioctl($pid_ht_out"set output od");
pid_ioctl($pid_ht_out"set output high");

ws_setup(0"thermometer""text.phpoc");

while(
1)
{  
    
convert_t();
    
$temp read_temp();

    
$temp sprintf("%.01f"$temp);

    if(
ws_state(0) == TCP_CONNECTED)
    {
        
ws_write(0"$temp\r\n");
    }

    
usleep(200000);
}
?>