Delphi - Is it possible to detect if the Screen monitor is ON or OFF by software? [duplicate] - delphi

Does anyone know if there is an API to get the current monitor state (on or off) in Windows (XP/Vista/2000/2003)?
All of my searches seem to indicate there is no real way of doing this.
This thread tries to use GetDevicePowerState which according to Microsoft's docs does not work for display devices.
In Vista I can listen to GUID_MONITOR_POWER_ON but I do not seem to get events when the monitor is turned off manually.
In XP I can hook into WM_SYSCOMMAND SC_MONITORPOWER, looking for status 2. This only works for situations where the system triggers the power off.
The WMI Win32_DesktopMonitor class does not seem to help out as well.
Edit: Here is a discussion on comp.os.ms-windows.programmer.win32 indicating there is no reliable way of doing this.
Anyone else have any other ideas?

GetDevicePowerState sometimes works for monitors. If it's present, you can open the \\.\LCD device. Close it immediately after you've finished with it.
Essentially, you're out of luck—there is no reliable way to detect the monitor power state, short of writing a device driver and filtering all of the power IRPs up and down the display driver chain. And that's not very reliable either.

You could hook up a webcam, point it at your screen and do some analysis on the images you receive ;)

Before doing anything based on the monitor state, just remember that users can use a machine with remote desktop of other systems that don't require a monitor connected to the machine - so don't turn off any visualization based on the monitor state.

You can't.
Look like all monitor power capabilities connected to the "power safe mode"
After searching i found here code that connecting between SC_MONITORPOWER message and system values (post number 2)
I use the code to testing if the system values is changing when i am manually switch off the monitor.
int main()
{
for(;monitorOff()!=1;)
Sleep(500);
return 0;
}//main
And the code is never stopped, no matter how long i am switch off my monitor.
There the code of monitorOff function:
int monitorOff()
{
const GUID MonitorClassGuid =
{0x4d36e96e, 0xe325, 0x11ce,
{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
list<DevData> monitors;
ListDeviceClassData(&MonitorClassGuid, monitors);
list<DevData>::iterator it = monitors.begin(),
it_end = monitors.end();
for (; it != it_end; ++it)
{
const char *off_msg = "";
//it->PowerData.PD_PowerStateMapping
if (it->PowerData.PD_MostRecentPowerState != PowerDeviceD0)
{
return 1;
}
}//for
return 0;
}//monitorOff
Conclusion : when you manually switch of the the monitor, you cant catch it by windows (if there is no unusual driver interface for this), because all windows capabilities is connected to "power safe mode".

In Windows XP or later you can use the IMSVidDevice Interface.
See
http://msdn.microsoft.com/en-us/library/dd376775(VS.85).aspx
(not sure if this works in Sever 2003)

With Delphi code, you can detect invalid monitor geomerty while standby in progress:
i := 0
('Monitor'+IntToStr(i)+': '+IntToStr(Screen.Monitors[i].BoundsRect.Left)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Top)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Right)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Bottom))
Results:
Monitor geometry before standby:
Monitor0: 0, 0, 1600, 900
Monitor geometry while standby in Deplhi7:
Monitor0: 1637792, 4210405, 31266576, 1637696
Monitor geometry while standby in DeplhiXE:
Monitor0: 4211194, 40, 1637668, 1637693

This is a really old post but if it can help someone, I have found a solution to detect a screen being available or not : the Connecting and Configuring Displays (CCD) API of Windows.
It's part of User32.ddl and the interesting functions are GetDisplayConfigBufferSizes and QueryDisplayConfig. It give us all informations that can be viewed in the Configuration Panel of windows.
In particular the PathInfo contains a TargetInfo property that have a targetAvailable flag. This flag seems to be correctly updated on all the configurations I have tried so far.
This allow you to know the state of every screens connected to the PC and set their configurations.
Here a CCD wrapper for .Net

If your monitor has some sort of built-in USB hub, you could try and use that to detect if the monitor is off/on.
This will of course only work if the USB hub doesn't stay connected when the monitor is consider "off".

Related

ESP8266 5v Relay USB Disconnection issue

Issue
-When using the ESP8266 wired up in this way it will randomly disconnect the USB interface when it powers the relay. It may then re-connect but is sporadic.
-The code can be viewed below, but essentially the relay is powered for 300ms then waits 10 seconds to loop.
Wiring Diagram https://i.stack.imgur.com/4mycx.png
Tests:
I have swapped out the relay, pump, ESP8266, aswell as re-wiring the circuit multiple times to check for a short. I also have a integer incrementing every loop cycle, when the ESP8266 is able to re-connect it will print this variable, which shows the board is not crashing:
Serial output
https://i.stack.imgur.com/ziM8g.png
I then modified the diagram so the 5v power was not in parallel, but where two different power sources, one for the ESP8266 and one for the pump circuit, however the same issue was observed:
Test Wiring Diagram https://i.stack.imgur.com/7S0aP.png
Question:
Why does the USB disconnect when sending the control signal to the relay?
Is there a way to mitigate this?
Code:
int relayInput = 5; // the input to the relay pin
int debug_test = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(relayInput, OUTPUT); // initialize pin as OUTPUT
}
void loop() {
// put your main code here, to run repeatedly:
debug_test ++ ;
Serial.println(debug_test);
digitalWrite(relayInput, HIGH); // turn relay on
Serial.println("Water on!");
delay(300);
digitalWrite(relayInput, LOW); // turn relay off
Serial.println("Water off!");
Serial.println("Waiting 10 seconds");
delay(10000);
}
Parts:
Pump - https://www.ebay.co.uk/itm/Mini-Water-Pump-DC-3V-4-5V-Fish-Tank-Fountain-Aquarium-Submersible-White-Parts/174211676084?hash=item288fd337b4:g:128AAOSwfQteYWF3
ESP8255 - https://www.amazon.co.uk/gp/product/B07F5FJSYZ/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1
Relay - https://www.amazon.co.uk/gp/product/B07BVXT1ZK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1
Ok, so researching in to this, it seems when the pump is on it pulls more current (amps) than the PC can provide.
This will be used connected to a external power source which should supply enough current to it, however I also wanted the flexibility to connect it to a PC with a serial connection to troubleshoot.
So in the end something like this:
https://i.stack.imgur.com/MKD1h.png
You are driving a 5v relay module with 3.3v output, which works perfectly for some people but it depends on the relay module and the board, this might be the problem. or the relay draws more than 12mA which is the maximum current can the ESP8266's GPIO deliver.
so I suggest you use an external power source for the relay and control it through the pin (D1 in your case).
Or just use a generic 5v relay with an external 5v power source and control it using a transistor, here is a circuit.
Additional information: https://electronics.stackexchange.com/questions/213051/how-do-i-use-a-5v-relay-with-a-3-3v-arduino-pro-mini?

non deterministic behaviour when using jungo driver to communicate with a PCI device

I have a PCI based Device, more specifically based on tms320c6000 DSP, I am trying to communicate (reading some registers) with this device through the Jungo WinDriver. Surprisingly it sometimes work and sometimes doesn't, when it doesn't system hang and I have to restart the system.
this is the snipped code which I used to read EMIF Registers, for example.
WD_TRANSFER tt[9];
BZERO(tt);
for (unsigned i = 0; i < 9; i++) {
tt[i].cmdTrans = RM_DWORD;
tt[i].dwPort = mmr + (i * 4);
}
WD_MultiTransfer(hDevice, &tt, 9);
mmr came from WD_CardRegister function which gave information about the PCI BARs and their mapped address (mmr is non prefechtable mapped memory).
I would be very grateful if someone could give me some hint about what might cause this problem.
Thanks
I am answering my question in case the problem happened to someone else.
there are sequence of actions which should be taken before using this device.
Warm reset through HDCR Register (set WARMRESET bit).
then the EMIF registers should be initialised, these are the values I used.
struct emif emif_val = {
0x00052078, //GBLCTL;
0x73a28e01, //CE1 Flash/FPGA;
0xffffffd3, //CE0 SDRAM;
0x00000000, //Reserved;
0x22a28a22, //CE2 Daughtercard 32-bit async
0x22a28a42, //CE3 Daughtercard 32-bit sync
0x63115000, //SDRAM contral, 4 banks
0x0000081b, //SDRAM timing
0x001faf4d //SDRAM extended control
};
and then you are able to access all address space of the device without any problem.
and for more information this linux source code could be very helpful

Why is TPrinter (XE7) suddenly having problems today?

I am using C++ Builder XE7 VCL.
Around August 11 2016 2:00pm UTC, I started receiving multiple complaints from my user base about printing problems. Most of these printing modules have proven stable for many years, and there were no updates to my project within the past 24 hours. I was able to reproduce similar problems on my development/test environment.
Without going into many details of my project, let me present a very simple printing program that is failing:
void __fastcall TForm1::PrintButtonClick(TObject *Sender)
{
// Test Print:
TPrinter *Prntr = Printer();
Prntr->Title = "Test_";
Prntr->BeginDoc();
Prntr->Canvas->Font->Size = 10;
Prntr->Canvas->TextOut(300,1050,"* * * Printing Test * * *");
if (Prntr->Printing) {
Prntr->EndDoc();
}
}
On the first attempt to print, everything works perfectly as expected. If I click the button a second time, TPrinter produces a small PDF, but the PDF file is actually corrupted and appears to have a file handle stuck to it.
If I click the button a third time, I get no printing and the following error message appears:
Printer is not currently printing.
My own test was done using a PDF printer driver, but the complaints I am receiving from users include a variety of local printers, network printers, PDF printers, etc.
In my actual project, I have try/catch exception handling, so the actual results are slightly different, but substantially similar to this result. The results show the hallmarks of instability and/or memory leaks without much in terms of error messages.
I suspect there may have been some Microsoft Windows updates that are tangling with Embarcadero DLLs, but I have not been able to verify this so far.
Is anyone else having similar problems?
The reason using a TPrintDialog or TPrinterSetupDialog "works" to fix the error is because they force the singleton TPrinter object (returned by the Vcl.Printers.Printer() function) to release its current handle to a printer if it has one, thus causing TPrinter.BeginDoc() to create a new handle. TPrinter releases its printer handle when:
it is being destroyed.
its NumCopies, Orientation, or PrinterIndex property is set.
its SetPrinter() method is called (internally by the PrinterIndex property setter and SetToDefaultPrinter() method, and by TPrintDialog and TPrinterSetupDialog).
Without doing that, calling TPrinter.BeginDoc() multiple times will just keep re-using the same printer handle. And apparently something about the recent Microsoft security update has now affected that handle reuse.
So, in short, (without uninstalling the Microsoft update) in between calls to BeginDoc() you need to do something that causes TPrinter to release and recreate its printer handle, and then the problem should go away. At least until Embarcadero can release a patch to TPrinter to address this issue. Maybe they could update TPrinter.EndDoc() or TPrinter.Refresh() to release the current printer handle (they currently do not).
Therefore, the following workaround resolves the printing issue without requiring any changes to the user interface:
void __fastcall TForm1::PrintButtonClick(TObject *Sender)
{
// Test Print:
TPrinter *Prntr = Printer();
Prntr->Title = "Test_";
Prntr->Copies = 1; // Here is the workaround
Prntr->BeginDoc();
if (Prntr->Printing) {
Prntr->Canvas->Font->Size = 10;
Prntr->Canvas->TextOut(300,1050,"* * * Printing Test * * *");
Prntr->EndDoc();
}
}
There are no Embarcadero DLLs involved in printing. TPrinter simply calls Win32 API GDI-based print functions directly.
The "Printer is not currently printing" error occurs when one of the following operations is performed on a TPrinter when its Printing property is false:
TPrinter::NewPage()
TPrinter::EndDoc()
TPrinter::Abort()
a TPrinter::Canvas subproperty is being changed.
the TPrinter::Canvas is being drawn on.
You are performing half of these operations in the test code you have shown, but you did not specify which line of code is actually throwing the error.
The Printing property simply returns the current value of the TPrinter::FPrinting data member, which is set to false only when:
the TPrinter object is initially created (the Printer() function returns a singleton object that is reused for the lifetime of the executable).
the Win32 API StartDoc() function fails inside of TPrinter::BeginDoc() (FPrinting is set to true before StartDoc() is called).
TPrinter::EndDoc() is called when Printing is true.
So, given the test code you have shown, there are two possibilities:
StartDoc() fails and you are not checking for that condition. BeginDoc() will not throw an error (VCL bug?!?), it will simply exit normally but Printing will be false. Add a check for that:
Prntr->BeginDoc();
if (Prntr->Printing) { // <-- here
Prntr->Canvas->Font->Size = 10;
Prntr->Canvas->TextOut(300,1050,"* * * Printing Test * * *");
Prntr->EndDoc();
}
the Printing property is getting set to false prematurely while you are in the process of printing something. The only ways that could happen in the code shown are if:
random memory is being corrupted, and TPrinter happens to be the victim.
multiple threads are manipulating the same TPrinter object at the same time. TPrinter is not thread-safe.
Since you can reproduce the problem in your development system, I suggest you enable Debug DCUs in the project options, then run your app in the debugger, and put a data breakpoint on the TPrinter::FPrinting data member. The breakpoint will be hit when FPrinting changes value, and you will be able to look at the call stack to see exactly which code is making that change.
Based on this information, I am going to go out on a limb and guess that the cause of your error is StartDoc() failing. Unfortunately, StartDoc() is not documented as returning why it fails. You certainly cannot use GetLastError() for that (most GDI errors are not reported by GetLastError()). You might be able to use the Win32 API Escape() or ExtEscape() function to retrieve an error code from the print driver itself (use TPrinter::Canvas::Handle as the HDC to query). But if that does not work, you won't be able to determine the reason of the failure, unless Windows is reporting an error message in its Event Log.
If StartDoc() really is failing, it is because of an Win32 API failure, not a VCL failure. Most likely the printer driver itself is failing internally (especially if a PDF print driver is leaving an open file handle to its PDF file), or Windows is failing to communicate with the driver correctly. Either way, it is outside of the VCL. This is consistent with the fact that the error started happening without you making any changes to your app. A Windows Update likely caused a breaking change in the print driver.
Try removing the following Windows update:
Security Update for Microsoft Windows (KB3177725)
MS16-098: Description of the security update for Windows kernel-mode drivers: August 9, 2016
This appears to resolve the issue for several test cases so far.
It started happening here today too. On my Windows 10 setup this would happen after calling TForm's Print() 3 times. I tried both the Microsoft Print to PDF and the Microsoft XPS Document Writer and both gave the same error.
I did some quick debugging and found that it's the call to StartDoc() that returns a value <= 0.
A temp fix until I can figure out what is really causing this is to re-create the Printer object in Printers by calling
Vcl.Printers.SetPrinter(TPrinter.Create).Free;
after calling anything that is using the Printer object. Might not be advisable to do that, but it solved my issue for now.
Looks like something is not released properly when calling EndDoc()
It seems that this is really a Microsoft problem and they should fix this buggy update. You can find more info at this on the company site.
Using a Printer Setup Dialog is only a workaround, not real solution, for this Microsoft bug. After confirmation, the printer setup dialog always creates a new handle for the printer. The next one or two print jobs will then succeed.
The patch should come from Microsoft, not from Embracadero. Thousands of programs are affected and it would be a massive waste of time and money to implement a workaround in all of them, if there is a bug in MS update.
I started experiencing the same weird behavior at more or less the same time, when running 32 bit Delphi applications built in XE7 on a Windows 10 64 bit system.
After uninstalling the latest security upgrade for Windows 10 (KB3176493), printing from these applications works normally again.
A rather surprising side effect of uninstalling this update seems to be that the file associations - which are the default programs for handling specific file types - are being reverted to Microsoft Windows default values...
The following variation of the code in the question will resolve the problem, but requires a TPrinterSetupDialog component added to the form:
void __fastcall TForm1::PrintButtonClick(TObject *Sender)
{
// Test Print:
TPrinter *Prntr = Printer();
Prntr->Title = "Test_";
PrinterSetupDialog1->Execute();
Prntr->BeginDoc();
if (Prntr->Printing) {
Prntr->Canvas->Font->Size = 10;
Prntr->Canvas->TextOut(300,1050,"* * * Printing Test * * *");
Prntr->EndDoc();
}
}
For program usage, the user will be presented with the printer setup dialog before proceeding to printing.
As to "why", my best guess at this point is that TPrinter used alone does not have all necessary permissions to access all necessary resources from Windows after the Security Update for Microsoft Windows (KB3177725) was implemented on Aug 10, 2016. Somehow a call to TPrinterSetupDialog (or TPrintDialog) before calling BeginDoc() sets up the necessary conditions for TPrinter to perform successfully.

Windows 10 IoT Raspberry Pi 2: DHT22/AM2302

I just wanted to start making experience with the DHT22/AM2302 (a temperature and humidity sensor), but I have no idea how to initialize and get the data of it ... I tried to use GpioPin:
gpioController = GpioController.GetDefault();
if(gpioController == null)
{
Debug.WriteLine("GpioController Initialization failed.");
return;
}
sensorPin = gpioController.OpenPin(7); //Exception throws here
sensorPin.SetDriveMode(GpioPinDriveMode.Input);
Debug.WriteLine(sensorPin.Read());
but get the exception: "A resource required for this operation is disabled."
After that I took a look at the library for the unixoids and found this:
https://github.com/technion/lol_dht22/blob/master/dht22.c
But I have no idea how to realize that in VCSharp using Windows 10, anyone an idea or experience?
Thank you very much in advance!
UPDATE:
I got the hint, that there is not GPIO-Pin 7 and this is true, so I re-tried it, but the GPIO-Output seems to be just HIGH or LOW ... So I have to use the I2C or the SPI ... According to this Project, I decided to try it out with SPI: http://microsoft.hackster.io/windowsiot/temperature-sensor-sample and making steps forward ... The difficulty now is to translate the above linked C-Library to the C-Sharp-SDK to receive the right data ...
private async void InitSPI()
{
try
{
var settings = new SpiConnectionSettings(SPI_CHIP_SELECT_LINE);
settings.ClockFrequency = 500000;
settings.Mode = SpiMode.Mode0;
string spiAqs = SpiDevice.GetDeviceSelector(SPI_CONTROLLER_NAME);
var deviceInfo = await DeviceInformation.FindAllAsync(spiAqs);
SpiDisplay = await SpiDevice.FromIdAsync(deviceInfo[0].Id, settings);
}
catch(Exception ex)
{
Debug.WriteLine("SPI Initialization failed: " + ex.Message);
}
}
This works not so well, to be clear: It works just once on starting up the raspberry pi2, then starting / remote debugging the application, but after exiting the application and re-start them, the SPI Initialization fails.
And now Im working on reading the data from the pin and will show some Code in a future update. Any comments, answers and or advices are still welcome.
DHT22 requires very precise timing. Although Raspberry PI/Windows 10 IoT core is extremely fast, since it's an operating system where other things need to happen unless you write some sort of low-level driver (not C#) you won't be able to generate the timings necessary to communicate with a DHT22.
What I do is use a cheap Arduino Mini Pro for about $5 with the sole purpose to generate and send the correct timings between the microcontroller and the Raspberry Pi, then setup some sort of communication channel between the Arduino Mini Pro (I2C, Serial) to pull the data from the Arduino.

get keyboard input contiki

I want to know how can I get a keyboard input in contiki os.
I already tried getchar(),getch(),scanf(),gets() and none worked, so I want to know if somebody can help me.
getchar,getch,scanf,gets are sort of POSIX things that read from files (e.g. stdin) --- these don't exist in Contiki (all though you could probably use them with the native platform).
So the first question to ask is what platform are you using and what do you mean by "keyboard". If keyboard means typing characters that are sent via a serial port from a computer then you have to know where they are received on the thing running Contiki. A typical arrangement is to receive characters on a uart, say, uart1.
In this case, contiki uses a callback such as uart1_input_handler that will be defined by the application. Platform main loops will check if there are characters to send to the input_handler and then check that an input_handler is defined. If so, will call something like uart1_input_handler(c).
You can see this code for the various platforms by grepping for uart1_input_handler:
platform/redbee-econotag/contiki-mc1322x-main.c: uart1_input_handler(uart1_getc());
cpu/msp430/dev/uart1x.c: if(uart1_input_handler(c)) {
cpu/stm32w108/dev/uart1.c: uart1_input_handler(c);
etc...
Some examples that register an input handler and process the characters:
example/shell:
/* set up the shell */
uart1_set_input(serial_line_input_byte);
serial_line_init();
serial_shell_init();
slip, in examples/ipv6/rpl-border-router/slip-bridge.c
slip_set_input_callback(slip_input_callback);
My guess for what you want to do would be to start with the shell examples and try to get those working.
The example cited below is from the Wiki pages of contiki on github. It demonstrates how the contiki specific mechanism for serial input works. Like mariano mentioned above that a callback has to be defined for the serial drivers specific to the platform you are using. I have used for ex. "rs232_set_input(RS232_PORT_0, serial_line_input_byte) ; " for my atmega128 MCU. The serial i/o drivers use this callback mechanism to post input characters to the "serial_line_process" defined in serial-line.c file. This process then broadcasts the serial_line_event_message to all processes along with the data read on the serial line. A process like the eg. stated below, can catch this event and process the input as per the requirements.
The callback mentioned above is defined in $(CONTIKI)/core/dev/serial-line.c. Check that out.
Once you initialise it using serial_line_init(), you are good to go.
#include "contiki.h"
#include "dev/serial-line.h"
#include <stdio.h>
PROCESS(test_serial, "Serial line test process");
AUTOSTART_PROCESSES(&test_serial);
PROCESS_THREAD(test_serial, ev, data)
{
PROCESS_BEGIN();
for(;;) {
PROCESS_YIELD();
if(ev == serial_line_event_message) {
printf("received line: %s\n", (char *)data);
}
}
PROCESS_END();
}
I assume you use COOJA (or maybe you connected a keyboard to your device so my answer will not be correct).
COOJA is an emulator, not a simulator.
If you want a responsive design, use the sensor button (on sky platform for example)
SENSORS_ACTIVATE(button_sensor);
/* Wait until we get a sensor event with the button sensor as data. */
PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event &&
data == &button_sensor);
Hope it helped.

Resources