Python Forum

Full Version: Newbie help combining two scripts
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Woo-hoo, almost there. Some kind of a decoding issue apparently :) Now I can get the actual temperature reading from xxx:8000/get-temp and the camera stream from xxx:8000/index.html

The only problem now is, that for some reason (the js-part?) I cannot fetch the temp data into the div.

# Web streaming example
# Source code from the official PiCamera package
# http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming

import os
import glob
import json
import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server
import time
from w1thermsensor import W1ThermSensor
PAGE="""\
<html>
<head>
<title>Kanikamera</title>

</head>
<body>
<center><h1>Kanikamera</h1></center>
<center><h3>L&auml;mp&ouml;tila</h3><h3 id="portfolio-code"></h3></center>
<center><img src="stream.mjpg" width="1280" height="720"></center>
<center><div id="temperature"></div></center>

<!--This is the script for displaying the temperature on the web page-->

<script>
function updateTemp(){
window.fetch('http://xxxxx.xxxxx.org:8000/get-temp', {method: 'get'}).then(r => r.json())
  .then(function(data){
   let el = document.getElementById('temperature')
  el.innerHTML = data.stringify() // you can do this better
})
  .catch(e => console.log("error ocurred..."))
}
 
 
// this executes only once, but you need to run it every second
updateTemp() // You probably need to run this continuously, e.g. using SetInterval function
 
</script>

</body>
</html>
"""
#This is the part to get the temperature
#os.system('modprscriptobe w1-gpio')
#os.system('modprobe w1-therm')  
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
  
def read_temp_raw():
     f = open(device_file, 'r')
     lines = f.readlines()
     f.close()
     return lines
  
def read_temp():
     lines = read_temp_raw()
     while lines[0].strip()[-3:] != 'YES':
         time.sleep(0.2)
         lines = read_temp_raw()
     equals_pos = lines[1].find('t=')
     if equals_pos != -1:
         temp_string = lines[1][equals_pos+2:]
         temp_c = float(temp_string) / 1000.0
         temp_f = temp_c * 9.0 / 5.0 + 32.0
         return temp_c, temp_f

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()
 
    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

#This is the part for the camera
class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/get-temp':
            self.send_response(200)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            tf, tc = read_temp()
            self.wfile.write(json.dumps({'temp_c':tf}).encode('utf-8'))
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()
class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True

with picamera.PiCamera(resolution='1280x720', framerate=24) as camera:
    output = StreamingOutput()
    #Uncomment the next line to change your Pi's Camera rotation (in degrees)
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()
You likely need to debug what is happening with js-part of the code. Open browser with your url,
Output:
let el = document.getElementById('temperature') el.innerHTML = data.stringify() // you can do this better
open developer tools (e.g. via inspecting some element on the page),
and put a breakpoint to let el .... or el.innerHTML .... The main question here is to inspect data variable (its value, does updateTemp read temp value correctly?).
(Oct-03-2020, 06:03 PM)emuola Wrote: [ -> ]Woo-hoo, almost there. Some kind of a decoding issue apparently :) Now I can get the actual temperature reading from xxx:8000/get-temp and the camera stream from xxx:8000/index.html

The only problem now is, that for some reason (the js-part?) I cannot fetch the temp data into the div.

# Web streaming example
# Source code from the official PiCamera package
# http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming

import os
import glob
import json
import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server
import time
from w1thermsensor import W1ThermSensor
PAGE="""\
<html>
<head>
<title>Kanikamera</title>

</head>
<body>
<center><h1>Kanikamera</h1></center>
<center><h3>L&auml;mp&ouml;tila</h3><h3 id="portfolio-code"></h3></center>
<center><img src="stream.mjpg" width="1280" height="720"></center>
<center><div id="temperature"></div></center>

<!--This is the script for displaying the temperature on the web page-->

<script>
function updateTemp(){
window.fetch('http://xxxxx.xxxxx.org:8000/get-temp', {method: 'get'}).then(r => r.json())
  .then(function(data){
   let el = document.getElementById('temperature')
  el.innerHTML = data.stringify() // you can do this better
})
  .catch(e => console.log("error ocurred..."))
}
 
 
// this executes only once, but you need to run it every second
updateTemp() // You probably need to run this continuously, e.g. using SetInterval function
 
</script>

</body>
</html>
"""
#This is the part to get the temperature
#os.system('modprscriptobe w1-gpio')
#os.system('modprobe w1-therm')  
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
  
def read_temp_raw():
     f = open(device_file, 'r')
     lines = f.readlines()
     f.close()
     return lines
  
def read_temp():
     lines = read_temp_raw()
     while lines[0].strip()[-3:] != 'YES':
         time.sleep(0.2)
         lines = read_temp_raw()
     equals_pos = lines[1].find('t=')
     if equals_pos != -1:
         temp_string = lines[1][equals_pos+2:]
         temp_c = float(temp_string) / 1000.0
         temp_f = temp_c * 9.0 / 5.0 + 32.0
         return temp_c, temp_f

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()
 
    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

#This is the part for the camera
class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/get-temp':
            self.send_response(200)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            tf, tc = read_temp()
            self.wfile.write(json.dumps({'temp_c':tf}).encode('utf-8'))
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()
class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True

with picamera.PiCamera(resolution='1280x720', framerate=24) as camera:
    output = StreamingOutput()
    #Uncomment the next line to change your Pi's Camera rotation (in degrees)
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()

Works!! :) Now I only need to make it look a bit nicer. How could "formulate" the JSON response displayed in the div? At the moment it looks like in the screen shot attached. How could I display only the temperature reading without the brackets and stuff?

Thank you soo much for your support scidam! Dance
Try the following:
PAGE="""\
<html>
<head>
<title>Kanikamera</title>
 
</head>
<body>
<center><h1>Kanikamera</h1></center>
<center><h3>L&auml;mp&ouml;tila</h3><h3 id="portfolio-code"></h3></center>
<center><img src="stream.mjpg" width="1280" height="720"></center>
<center><div id="temperature" style="font-size: 20px;"></div></center>
 
<!--This is the script for displaying the temperature on the web page-->
 
<script>
function updateTemp(){
window.fetch('http://xxxxx.xxxxx.org:8000/get-temp', {method: 'get'}).then(r => r.json())
  .then(function(data){
   let el = document.getElementById('temperature')
    el.innerHTML = data['temp_c'] + " degrees. Time of the last measurement: " + getDateTime();

})
  .catch(e => console.log("error ocurred..."))
}
  
  
// this executes only once, but you need to run it every second
updateTemp() // You probably need to run this continuously, e.g. using SetInterval function
  


function getDateTime() {
    var now     = new Date(); 
    var year    = now.getFullYear();
    var month   = now.getMonth()+1; 
    var day     = now.getDate();
    var hour    = now.getHours();
    var minute  = now.getMinutes();
    var second  = now.getSeconds(); 
    if(month.toString().length == 1) {
            month = '0'+month;
    }
    if(day.toString().length == 1) {
            day = '0'+day;
    }   
    if(hour.toString().length == 1) {
            hour = '0'+hour;
    }
    if(minute.toString().length == 1) {
            minute = '0'+minute;
    }
    if(second.toString().length == 1) {
            second = '0'+second;
    }   
    var dateTime = year+'/'+month+'/'+day+' '+hour+':'+minute+':'+second;   
        return dateTime;
}

updateTemp();
setInterval(updateTemp, 5000);  // update measurements every 5 sec

</script>
 
</body>
</html>
"""
There are still a lot of possibilities to change your page appearance. Try to define custom style for your div,
use span tags to change style of the text inside div, etc.
Pages: 1 2