| 1 | // Copyright (C) 2016 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
| 3 |  | 
| 4 | #include "genericalssensor.h" | 
| 5 | #include <QDebug> | 
| 6 |  | 
| 7 | char const * const genericalssensor::id("generic.als" ); | 
| 8 |  | 
| 9 | genericalssensor::genericalssensor(QSensor *sensor) | 
| 10 |     : QSensorBackend(sensor) | 
| 11 | { | 
| 12 |     lightSensor = new QLightSensor(this); | 
| 13 |     lightSensor->addFilter(filter: this); | 
| 14 |     lightSensor->connectToBackend(); | 
| 15 |  | 
| 16 |     setReading<QAmbientLightReading>(&m_reading); | 
| 17 |     setDataRates(lightSensor); | 
| 18 | } | 
| 19 |  | 
| 20 | void genericalssensor::start() | 
| 21 | { | 
| 22 |     lightSensor->setDataRate(sensor()->dataRate()); | 
| 23 |     lightSensor->setAlwaysOn(sensor()->isAlwaysOn()); | 
| 24 |     lightSensor->start(); | 
| 25 |     if (!lightSensor->isActive()) | 
| 26 |         sensorStopped(); | 
| 27 |     if (lightSensor->isBusy()) | 
| 28 |         sensorBusy(); | 
| 29 | } | 
| 30 |  | 
| 31 | void genericalssensor::stop() | 
| 32 | { | 
| 33 |     lightSensor->stop(); | 
| 34 | } | 
| 35 |  | 
| 36 | struct lux_limit { | 
| 37 |     int min; | 
| 38 |     int max; | 
| 39 | }; | 
| 40 |  | 
| 41 | // Defines the min and max lux values that a given level has. | 
| 42 | // These are used to add histeresis to the sensor. | 
| 43 | // If the previous level is below a level, the lux must be at or above the minimum. | 
| 44 | // If the previous level is above a level, the lux muyt be at or below the maximum. | 
| 45 | static lux_limit limits[] = { | 
| 46 |     { .min: 0,    .max: 0    }, // Undefined (not used) | 
| 47 |     { .min: 0,    .max: 5    }, // Dark | 
| 48 |     { .min: 10,   .max: 50   }, // Twilight | 
| 49 |     { .min: 100,  .max: 200  }, // Light | 
| 50 |     { .min: 500,  .max: 2000 }, // Bright | 
| 51 |     { .min: 5000, .max: 0    }  // Sunny | 
| 52 | }; | 
| 53 |  | 
| 54 | #if 0 | 
| 55 | // Used for debugging | 
| 56 | static QString light_level(int level) | 
| 57 | { | 
| 58 |     switch (level) { | 
| 59 |     case 1: | 
| 60 |         return QLatin1String("Dark" ); | 
| 61 |     case 2: | 
| 62 |         return QLatin1String("Twilight" ); | 
| 63 |     case 3: | 
| 64 |         return QLatin1String("Light" ); | 
| 65 |     case 4: | 
| 66 |         return QLatin1String("Bright" ); | 
| 67 |     case 5: | 
| 68 |         return QLatin1String("Sunny" ); | 
| 69 |     default: | 
| 70 |         return QLatin1String("Undefined" ); | 
| 71 |     } | 
| 72 | } | 
| 73 | #endif | 
| 74 |  | 
| 75 | bool genericalssensor::filter(QLightReading *reading) | 
| 76 | { | 
| 77 |     // It's unweildly dealing with these constants so make some | 
| 78 |     // local aliases that are shorter. This makes the code below | 
| 79 |     // much easier to read. | 
| 80 |     enum { | 
| 81 |         Undefined = QAmbientLightReading::Undefined, | 
| 82 |         Dark = QAmbientLightReading::Dark, | 
| 83 |         Twilight = QAmbientLightReading::Twilight, | 
| 84 |         Light = QAmbientLightReading::Light, | 
| 85 |         Bright = QAmbientLightReading::Bright, | 
| 86 |         Sunny = QAmbientLightReading::Sunny | 
| 87 |     }; | 
| 88 |  | 
| 89 |     int lightLevel = m_reading.lightLevel(); | 
| 90 |     qreal lux = reading->lux(); | 
| 91 |  | 
| 92 |     // Check for change direction to allow for histeresis | 
| 93 |     if (lightLevel < Sunny    && lux >= limits[Sunny   ].min) lightLevel = Sunny; | 
| 94 |     else if (lightLevel < Bright   && lux >= limits[Bright  ].min) lightLevel = Bright; | 
| 95 |     else if (lightLevel < Light    && lux >= limits[Light   ].min) lightLevel = Light; | 
| 96 |     else if (lightLevel < Twilight && lux >= limits[Twilight].min) lightLevel = Twilight; | 
| 97 |     else if (lightLevel < Dark     && lux >= limits[Dark    ].min) lightLevel = Dark; | 
| 98 |     else if (lightLevel > Dark     && lux <= limits[Dark    ].max) lightLevel = Dark; | 
| 99 |     else if (lightLevel > Twilight && lux <= limits[Twilight].max) lightLevel = Twilight; | 
| 100 |     else if (lightLevel > Light    && lux <= limits[Light   ].max) lightLevel = Light; | 
| 101 |     else if (lightLevel > Bright   && lux <= limits[Bright  ].max) lightLevel = Bright; | 
| 102 |  | 
| 103 |     //qDebug() << "lightLevel" << light_level(lightLevel) << "lux" << lux; | 
| 104 |  | 
| 105 |     if (static_cast<int>(m_reading.lightLevel()) != lightLevel || m_reading.timestamp() == 0) { | 
| 106 |         m_reading.setTimestamp(reading->timestamp()); | 
| 107 |         m_reading.setLightLevel(static_cast<QAmbientLightReading::LightLevel>(lightLevel)); | 
| 108 |  | 
| 109 |         newReadingAvailable(); | 
| 110 |     } | 
| 111 |  | 
| 112 |     return false; | 
| 113 | } | 
| 114 |  | 
| 115 |  |