Programmatically Turning Off the Screen

I sometimes work on systems that control displays that run for most of the day. But there are “quiet hours” during which those screens show no content, and we would rather them be turned off. Having some downtime saves on resources, including the life of the display. The way this is handled differs from one solution to another. Sometimes we use third-party hardware to control the screens according to a schedule. Other times, we might enter the schedule into the display settings. I’m working on a solution that is a bit more varied from day-to-day. The schedule options don’t work here.

I want a display to turn on at the start of the day and turn off a little after sunset. Calculating the time of sunrise and sunset is pretty easy. I keep a web app on GitHub just for that purpose (Note: since sunrise time is location dependent, this webapp will ask for permission to use your location). The challenge is how do I tell the screen to turn on and off. Ideally, I would use HDMI-CEC. This is the protocol that you see used in many consumer devices (such as a PlayStation or Chromecast) to turn a television on and change the input. Unfortunately, HDMI-CEC is not generally supported by computer video cards. That’s not an option. But many displays have an option to turn off when there is no video signal and to turn on when one is received. An achievable approach would be to have the computer to simply turn off its HDMI output.

On Windows, we can achieve this with a single API call to SendMessage(). The SendMessage() is used by a broad range of Windows components for communicating with each other and invoking functionality. The first argument to this function is a handle for the window that the message is to be sent to. The window handle constant HWND_BROADCAST sends a message to all top-level windows. It also can be used to send messages to the system itself. There are three other parameters in SendMessage(). It also takes the command for the message and two parameters. The command that we need to turn the display off is WM_SYSCOMMAND. This means that we want to execute a system command. The third parameter identifies which command that we want to invoke. In our case, it is SC_MONITORPOWER (System Command Monitor Power). The by the value passed in the fourth position, the command can tell the display output to turn on (-1), off(2), or sleep mode(1).

Using this command, I can turn the display off. It will turn back on if the mouse is moved or a key on the keyboard is pressed. Using the command to turn back on is a bit different. For my scenario, the computers reboot daily at least an hour before they are needed. This is enough to turn the display back on. I’ve tried making the function call with the parameter to turn the display on. But the result varies. I’ve had better success if I make the system call that makes the system process a keyboard input or mouse movement. You would think that the SendMessage() call could be used for this purpose too. You would only use that function to send a key press message to a specific window. To have the system act as though there were a user input I need to use the SendInput() function. A mouse move input is the safest input to generate. Key input might activate functionality in applications that one might not intend to invoke.

INPUT input = { 0 };
input.type = INPUT_MOUSE;
input.mi.dx = 10;
input.mi.dy = 10;
input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
if (SendInput(1, &input, sizeof(INPUT)) == 0)
{
	std::wcerr << L"Error sending mouse move input to wake up the screen. Error code: 0x" << std::hex << GetLastError() << std::endl;
}

The source code and compiled binaries for this program can be found on my GitHub page in this repository. I’ve made a command line utility that takes a single argument. The value of the argument can be on, off, or sleep. I suggest **not** running it on a laptop. When I tried these commands on a laptop I got unusual results. They may generally work better on computers that use external displays.


Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Bluesky: @j2i.net

Avoiding eSIM | Opinion

eSIMs, or embedded SIM, is integration of the SIM hardware into a phone. Instead of installing a physical SIM card a phone has similar hardware integrated into itself with rewritable memory. To update the SIM a new byte stream containing the updated program or data can be transferred to the embedded SIM hardware. Most material I come across about them characterize them as providing a way to manage phones with more ease and an overall improvement. They are described as being managed with ease. All that one needs is to ensure their phone software is up to date, that you have an Internet connection, and that you select a few menu options to add or move an eSIM to a phone. I see these requirements as a vulnerability and a loss in flexibility. For a physical SIM, the most challenging step is locating a paperclip or SIM ejection tool.

I already had this disposition, but I got to experience it after someone’s phone was destroyed in a car accident. The person generally relied on the contacts feature of their phone to call people and didn’t actually know the important phone numbers1. I took the person’s phone and told them “to reach me, call your phone number. I will put the SIM card in another phone.” I arrived home, opened the SIM tray, and found it empty. Suddenly, I realized this was going to be more complicated than I thought. The steps needed to transfer an eSIM were completely accessible. One cannot run the eSIM transfer app on a phone with a pulverized screen and will not turn on. The person that managed the phone account lived in another state and I had never had direct contact with them before.

I found the person’s contact information and contacted them. That started an exercise of trying to establish trust with a person that thought that I might be a scammer. That exercise is worthy of its own story. But I established trust. The carrier told us that for what we needed to do, someone authorized on the account had to physically be in a store. Since we were located on opposite coasts, that solution opened up the possibility of a SIM being activated and mailed to my posts. That’s not a desirable solution. For a more expedient resolution, the person added me as an authorized person on the account. I went to a carrier location to start the transfer. This was complicated by the carrier wanting to send me a text message with a validation code. The carrier sent the message to the phone that was destroyed! To validate, I had them send the validation message to the person that was on the opposite coast, called them from my own phone, and retrieved the validation code, and got the account transferred to the SIM. FINALLY! An actual, physical, SIM!

The phone I use has capabilities for eSIM, as does my smartwatch. But I prefer to use a physical SIM because it allows me more freedom in moving service to another phone without the carrier being the middleman. I’ve been in other scenarios where I’ve needed to temporarily move service to another device. Usually, when I travel, I have an extra (usually older) phone that doesn’t have service. If my primary phone were damaged or failed (it’s happened once before) I would move the SIM to the other phone. I have a parent whose battery started to swell, and the phone shut down. In all these scenarios, the ability to move the SIM card offered a same-day solution. The solution that requires another entity be involved adds failure points that I would rather not be subject to.

  1. Having run into other people that have found themselves in this scenario, I only call my most important people by dialing their numbers from memory to better ensure that I do not forget them. ↩︎

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Bluesky: @j2i.net