Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › C++, Loops, and User Interactions
New Posts  All Forums:Forum Nav:

C++, Loops, and User Interactions - Page 2

post #11 of 16
Thread Starter 
Quote:
Originally Posted by stolemyowncar View Post

^ Right, multithreading often introduces more problems than it solves (most of those problems that it "solves" can be solved by better coding, too).
Then it's pretty simple. You open the device, then you go off and do something else for a second or two. Then you come back and read everything from your buffer (supposing it sends it out while you're doing that). All I posted in my link was how to implement a simple timer interrupt in C++. Every X seconds, you do Y.

So in your case, this might be useful:

Open Device->Set Timer for X seconds-> Read from device->Open device (etc)

Supposing that doesn't work:

Also, nonblocking reads giving you null values when there is nothing there is quite normal. What you do in that case is you simply check how many bytes or bits you received and then try again later. Just keep appending what you get in to what you've got, and then when you have the entire message, do your processing on it.

If you really wanted an alternative for this using multithreading your easiest option would be moving the temperature read to its own thread and then using a shared variable to store the temperature.



Believe me I've dealt with much worse than that thing you've got there. The digital laser rangefinder I used on my senior design project just output serial characters in an utterly constant stream and would utterly overflow the serial buffer in absolutely no time at all. An interrupt fixed that, and it's probably the only thing that could fix that. I can't really go into specifics on that one though.

I see what you're saying, so if I do a non-blocking read each loop, I can pick up X amount of bytes per loop and then once I grab all the bytes I'll move to manipulate the data. In between each read attempt, I can do my UI updates.

I'll have to experiment to see how this works; I'm not sure if it will store the output data in a buffer somewhere while waiting to be read, or if I have to catch it as it's output. I'll report back my findings.

Thanks for all the input everyone.
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
post #12 of 16
Thread Starter 
Alrighty! So it appears that opening the file prompts the device to start working on outputting the data. Multiple reads after opening once yields the same results over and over (as expected).

The good news, and I think you suspected this from the get-go stolemyowncar (I don't think I was fully understanding what you were saying), but the open function is non-blocking. That means that after a period of time (1-2 seconds) of doing something else a read is instantaneous.

So I suppose now I can probably use a timer interrupt to read a period of time after the device is opened. Perhaps even a simpler solution might be to use the system time that only executes reads/opens/close after a delta time.

Either way, this thread has really cleared up a lot for me. I'll keep trucking away and I'll be sure to let you know if I run into any other terribly simple problems... tongue.gif
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
post #13 of 16
Thread Starter 
If interested, here is a first pass at the tempsensor class as a result of the findings in this thread.
tempsensor.h (Click to show)
Code:
#include <wiringPi.h>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iostream>
using namespace std;

#ifndef TEMPSENSOR
#define TEMPSENSOR

class Tempsensor {
        public:
                Tempsensor(char* sensor, int heatPin, int coolPin, int fanPin);
                ~Tempsensor();

                float getTemp(bool fahrenheit);
        private:
                float convert(float tempC);

                time_t openTime; //Stores the time in which the sensor 'file' was opened.
                bool open; //Flags whether or not the sensor has been opened.
                bool read; //Flags whether or not the sensor has been read.
                char* rawOutput; //Raw output from sensor.
                float temperature; //Last read temperature.
                ifstream tempFile;

                char* sensor; //File location of the sensor output.
                const int HEAT; //WiringPi pin number for the heat relay.
                const int COOL; //WiringPi pin number for the cool relay.
                const int FAN; //WiringPi pin number for the fan relay.
                const int DELAY; //Delay in seconds between opening and reading.
                const int SIZE; //Size of raw output array.
};

#endif
tempsensor.cpp (Click to show)
Code:
#include "tempsensor.h"

Tempsensor::Tempsensor(char* sensor, int heatPin, int coolPin, int fanPin) :
                        HEAT(heatPin), COOL(coolPin), FAN(fanPin), DELAY(3), SIZE(256) {

        this->sensor = new char[strlen(sensor) +1];
        strcpy(this->sensor, sensor);

        open = false;
        read = false;
}


Tempsensor::~Tempsensor() {
        delete sensor;
        sensor = NULL;
}


float Tempsensor::getTemp(bool fahrenheit) {
        if(!open) {
                tempFile.open(sensor, ifstream::in);
                openTime = time(NULL);
                open = true;
        }   

        if(!read) {
                if(difftime(time(NULL), openTime) >= DELAY) {
                        rawOutput = new char[SIZE];

                        tempFile.read(rawOutput, SIZE);
                        cout << rawOutput << endl;

                        delete rawOutput;
                        rawOutput = NULL;
                        read = true;
                }   
        }   
        else {
                tempFile.close();
                open = false;
                read = false;
        }   
}
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
post #14 of 16
Yep, looks like you got it. That would have been one of the first things I would have tried but hey that's what experience is for; the constant nonblocking read, when I thought about it again... would be rather iffy because the definition of "append" in that case is a bit vague. Anyway just try to tweak that time down as low as you can for a bit more responsiveness... well unless you don't care about the refresh rate of the temperature on the phone end. You'll probably also not need any kind of multithreading for this.

Looks like you went with the "pseudo"-timer interrupt solution that I mentioned, but that's really not a big deal. The boolean statements that you'll be running constantly are pretty fast for processors to handle.
post #15 of 16
Thread Starter 
Quote:
Originally Posted by stolemyowncar View Post

Yep, looks like you got it. That would have been one of the first things I would have tried but hey that's what experience is for; the constant nonblocking read, when I thought about it again... would be rather iffy because the definition of "append" in that case is a bit vague. Anyway just try to tweak that time down as low as you can for a bit more responsiveness... well unless you don't care about the refresh rate of the temperature on the phone end. You'll probably also not need any kind of multithreading for this.

Looks like you went with the "pseudo"-timer interrupt solution that I mentioned, but that's really not a big deal. The boolean statements that you'll be running constantly are pretty fast for processors to handle.

Experience is huge; this is my first dive into interfacing with hardware in my programs, so there has been a lot to take in.

I also ended up finding out that non-blocking reads are apparently not possible with C++ on Linux, at least with the standard libraries. I saw mention of a Boost library that might have helped, but it sounded like it might not have been worth the effort. I'm glad this driver ended up working like it did; much easier to open, wait, then read.
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
post #16 of 16
Thread Starter 
Well, I'm a glutton for punishment and decided I wanted to multi-thread this program... I was fairly surprised to find that with the Boost library, it really isn't all that much different from threading on Android. Anyway, here's the code; standard "code in progress, please suggest improvements" rules apply:
main.cpp (Click to show)
Code:
#include "thermostat.h"
#include "tempsensor.h"

void triggerLoop();

int main() {
        const int HEATPIN = 0;
        const int COOLPIN = 2;
        const int FANPIN = 3;
        const bool FAHRENHEIT = true;

        char* sensor = new char[strlen("/sys/bus/w1/devices/28-0000052fcf7f/w1_slave") +1];
        strcpy(sensor, "/sys/bus/w1/devices/28-0000052fcf7f/w1_slave");

        Thermostat* thermostat = new Thermostat((float)68.0, (float)76.0, HEATPIN, COOLPIN, FANPIN);
        Tempsensor* tempsensor = new Tempsensor(sensor, FAHRENHEIT);

        tempsensor->startReadLoop();

        //For testing purposes:
        float temperature;
        
        for(int i = 0; i < 300; ++i) {
                temperature = tempsensor->threadedGetTemp();
                thermostat->checkState(temperature);

                cout << "Temperature: " << temperature << endl;
                cout << thermostat->getState() << endl << endl; 

                //thermostat->checkState(tempsensor->threadedGetTemp());
        }

        tempsensor->endReadLoop();

        if(sensor) {
                delete sensor;
                sensor = NULL;
        }

        if(thermostat) {
                delete thermostat;
                thermostat = NULL;
        }

        if(tempsensor) {
                delete tempsensor;
                tempsensor = NULL;
        }

        return 0;
}
thermostat.cpp (Click to show)
Code:
#include "thermostat.h"

Thermostat::Thermostat(float heatTemp, float coolTemp, int heatPin, int coolPin, int fanPin) : 
                        AVESIZE(10), HEATPIN(heatPin), COOLPIN(coolPin), FANPIN(fanPin) {
        tempAve = NULL;
        currentAve = 0.0;
        heat = heatTemp;
        cool = coolTemp;
        state = 0; //0 = System Off; 1 = Cool On; 2 = Heat On;
        fan = false;

        wiringPiSetup();
        pinMode(HEATPIN, OUTPUT); //Heat
        pinMode(COOLPIN, OUTPUT); //Cool
        pinMode(FANPIN, OUTPUT); //Fan

        digitalWrite(HEATPIN, LOW);
        digitalWrite(COOLPIN, LOW);
        digitalWrite(FANPIN, LOW);

}

Thermostat::~Thermostat() {
        delete tempAve;
        tempAve = NULL;

        //Cleanup
        pinMode(HEATPIN, INPUT);
        pinMode(COOLPIN, INPUT);
        pinMode(FANPIN, INPUT);
}

void Thermostat::setFanState(bool fanState) {
        fan = fanState;
}

bool Thermostat::fanState() {
        if(fan) { return true; }
        else if(state != 0) { return true; }
        else { return false; }
}

bool Thermostat::heatState() {
        if(state == 2) { return true; }
        else { return false; }
}

bool Thermostat::coolState() {
        if(state == 1) { return true; }
        else { return false; }
}


char* Thermostat::getState() {
        if(state == 0) { return "System Off"; }
        else if(state == 1) { return "Cooling"; }
        else if(state == 2) { return "Heating"; }
}


float Thermostat::runningAve(float tempF) {
        float total = 0.0;

        if(!tempAve) {
                tempAve = new float[AVESIZE + 1];

                for(int i = 0; i < AVESIZE; ++i) {
                        tempAve[i] = tempF;
                }
        }

        else {
                for(int i = 0; i < AVESIZE - 1; ++i) {
                        tempAve[i+1] = tempAve[i];
                }

                tempAve[0] = tempF;
        }

        for(int i = 0; i < AVESIZE; ++i) {
                total += tempAve[i];
        }

        return total / (float)AVESIZE;
}

void Thermostat::checkState(float temp) {
        //If the system is currently off...
        if(state == 0) {
                //Keep system off if temperature is between heat and cool.
                if(temp < cool && temp > heat) {
                        state = 0;
                        systemOff();
                }
                //Turn on cool if temperature is above cool.
                else if(temp > cool) {
                        state = 1;
                        enableCool();
                }
                //Turn on heat if temperature is below heat.
                else if(temp < heat) {
                        state = 2;
                        enableHeat();
                }
        }
        //If the system is currently cooling...
        else if(state == 1) {
                //If the temperature is two degrees below cool, turn system off.
                if(temp < (cool - 2.0)) {
                        state = 0;
                        systemOff();
                }
        }
        //If the system is currently heating...
        else if(state == 2) {
                //If the temperature is two degrees above hot, turn system off.
                if(temp > (heat + 2.0)) {
                        state = 0;
                        systemOff();
                }
        }
}

void Thermostat::enableHeat() {
        digitalWrite(COOLPIN, LOW);
        digitalWrite(HEATPIN, HIGH);
        enableFan();
}

void Thermostat::enableCool() {
        digitalWrite(HEATPIN, LOW);
        digitalWrite(COOLPIN, HIGH);
        enableFan();
}

void Thermostat::enableFan() {
        digitalWrite(FANPIN, HIGH);
}

void Thermostat::systemOff() {
        digitalWrite(COOLPIN, LOW);
        digitalWrite(HEATPIN, LOW);

        //If the fan was manually switched on, keep in on...
        if(fan) { digitalWrite(FANPIN, HIGH); }
        //Otherwise, shut it off.
        else { digitalWrite(FANPIN, LOW); }
}
thermostat.h (Click to show)
Code:
#include <wiringPi.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

#ifndef THERMOSTAT
#define THERMOSTAT

class Thermostat {
        public:
                Thermostat(float heatTemp, float coolTemp, int heatPin, int coolPin, int fanPin);
                ~Thermostat();

                void setCool(float temp);
                void setHeat(float heat);

                void checkState(float temp);
                void setFanState(bool fanState);
                bool fanState();
                bool heatState();
                bool coolState();
                char* getState();
        private:
                float runningAve(float tempF);

                void enableCool();
                void enableHeat();
                void enableFan();
                void systemOff();

                float * tempAve;
                float currentAve;
                float heat;
                float cool;
                int state;
                bool fan;

                const int HEATPIN;
                const int COOLPIN;
                const int FANPIN;
                const int AVESIZE;
};

#endif
tempsensor.cpp (Click to show)
Code:
#include "tempsensor.h"

Tempsensor::Tempsensor(char* sensor, bool fahrenheit) : DELAY(3), SIZE(80) {

        this->sensor = new char[strlen(sensor) +1];
        strcpy(this->sensor, sensor);

        tempFile.open(this->sensor, ifstream::in);
        rawOutput = new char[SIZE];

        tempFile.read(rawOutput, SIZE);

        if(fahrenheit) {
                temperature = convert(parse(rawOutput));
        }
        else {
                temperature = parse(rawOutput);
        }

        delete rawOutput;
        rawOutput = NULL;

        tempFile.close();

        openTime = 0; //Sets the open time to Jan 1, 1970 so the first read is immediate.
        end = false;
        open = false;
        read = false;

        this->fahrenheit = fahrenheit;

        endMutex = new boost::mutex();
        tempMutex = new boost::mutex();
}


Tempsensor::~Tempsensor() {
        if(sensor) {
                delete sensor;
                sensor = NULL;
        }

        if(rawOutput) {
                delete rawOutput;
                rawOutput = NULL;
        }

        if(loopThread) {
                delete loopThread;
                loopThread = NULL;
        }
}


float Tempsensor::getTemp() {
        if(!open) {
                tempFile.open(sensor, ifstream::in);
                openTime = time(NULL);
                open = true;
                read = false;
        }

        if(!read) {
                if(difftime(time(NULL), openTime) >= DELAY) {
                        rawOutput = new char[SIZE];

                        tempFile.read(rawOutput, SIZE);

                        if(fahrenheit) {
                                temperature = convert(parse(rawOutput));
                        }
                        else {
                                temperature = parse(rawOutput);
                        }

                        delete rawOutput;
                        rawOutput = NULL;
                        read = true;
                }
        }
        else {
                tempFile.close();
                open = false;
                read = false;
        }

        return temperature;
}


float Tempsensor::threadedGetTemp() {
        boost::lock_guard<boost::mutex> guard(*tempMutex);
        return temperature;
}


void Tempsensor::startReadLoop() {
        endMutex->lock();
        end = false;
        endMutex->unlock();

        loopThread = new boost::thread(boost::bind(&Tempsensor::loop, this));

}


void Tempsensor::loop() {
        bool quit = false;

        while(!quit) {
                tempFile.open(sensor, ifstream::in);

                rawOutput = new char[SIZE];

                tempFile.read(rawOutput, SIZE);

                tempFile.close();

                if(fahrenheit) {
                        tempMutex->lock();
                        temperature = convert(parse(rawOutput));
                        tempMutex->unlock();
                }
                else {
                        tempMutex->lock();
                        temperature = parse(rawOutput);
                        tempMutex->unlock();
                }

                delete rawOutput;
                rawOutput = NULL;

                endMutex->lock();
                quit = end;
                endMutex->unlock();
        }

}


void Tempsensor::endReadLoop() {
        endMutex->lock();
        end = true;
        endMutex->unlock();

        loopThread->join();
}


float Tempsensor::convert(const float & tempC) {
        return (tempC * (9.0/5.0)) + 32;
}


float Tempsensor::parse(const char * rawOutput) {
        char* temp;
        float tempC;

        temp = new char[10];
        int size = strlen(rawOutput);

        strncpy(temp, &rawOutput[size -6], 5);

        /*for(int i = size; i >= 0; --i) {
                cout << rawOutput[i] <<endl;
                if(rawOutput[i] == '=') {
                        strncpy(temp, &rawOutput[i +1], size - (i +1));
                        break;
                }
        }*/

        tempC = atof(temp);

        delete temp;
        temp = NULL;
        return tempC / 1000.0;
}
tempsensor.h (Click to show)
Code:
#include <cstring>
#include <ctime>
#include <fstream>
#include <stdlib.h>
#include <boost/thread/thread.hpp>
using namespace std;

#ifndef TEMPSENSOR
#define TEMPSENSOR

class Tempsensor {
        public:
                Tempsensor(char* sensor, bool fahrenheit);
                ~Tempsensor();

                //Use getTemp() when the loop checking the temperature is external.
                float getTemp();

                //Use threadedGetTemp() after startReadLoop() has been called to get the last temp reading.
                float threadedGetTemp();
                void startReadLoop();
                void endReadLoop();
        private:
                boost::thread * loopThread;
                boost::mutex * endMutex;
                boost::mutex * tempMutex;

                static float convert(const float & tempC);
                static float parse(const char * rawOutput);
                void loop();

                time_t openTime; //Stores the time in which the sensor 'file' was opened.
                bool end; //Flags whether or not the read loop should quit.
                bool open; //Flags whether or not the sensor has been opened.
                bool read; //Flags whether or not the sensor has been read.
                bool fahrenheit; //Flags whether or not the temperature should be converted to fahrenheit.
                char* rawOutput; //Raw output from sensor.
                float temperature; //Last read temperature.
                ifstream tempFile;

                char* sensor; //File location of the sensor output.
                const int DELAY; //Delay in seconds between opening and reading.
                const int SIZE; //Size of raw output array.
};

#endif

Next up: Implementing user interactions and an LCD panel, both of which I imagine will operate on the same thread.
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
Perpetual Upgrade
(17 items)
 
Server
(17 items)
 
Galago UltraPro
(9 items)
 
CPUMotherboardGraphicsRAM
i7-4770K MSI Z97M Gaming Zotac GTX 1080 AMP! Edition (2x4GB) Corsair DDR3-2000 
Hard DriveHard DriveCoolingCooling
128GB Crucial M4 (2x) 500GB RAID 0 Swiftech Apogee Black Ice GT Stealth 240 
OSKeyboardPowerCase
Windows 10 Pro 64bit Corsair K70 Vengence Seasonic X650 Aerocool DS Cube 
MouseAudio
Logitech G500 ASUS Xonar DX 
CPUMotherboardGraphicsRAM
Phenom II X4 965 MSI 870A-G54 nVidia 8400GS (2x2GB) Patriot DDR3-1600 
RAMHard DriveHard DriveCooling
(2x4GB) Patriot DDR3-1600 (3x) 320GB RAID 5 (1x) 1TB Backup Storage Coolermaster TX3 
OSPowerOther
Proxmox Hypervisor Antec TruePower 430W HP Smart Array P400 
CPUGraphicsRAMHard Drive
Intel i7-4750HQ Intel Iris Pro Graphics 5200  (2 x 4GB) DDR3-1600 90GB Intel mSATA SSD 
Hard DriveOSOSMonitor
500GB 5400RPM HDD Ubuntu Gnome 15.10 Windows 10 14" 1080p ColorPro IPS 
Case
Galago UltraPro 
  hide details  
Reply
New Posts  All Forums:Forum Nav:
  Return Home
  Back to Forum: Coding and Programming
Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › C++, Loops, and User Interactions