使用nextjs实现通过web控制屏幕亮度

1,328 阅读2分钟

首先,创建一个nextjs(typescript)的项目:

yarn create next-app --example with-typescript brightness

然后,添加nircmd库:

yarn add nircmd

nircmd 可以方便地调用windows的系统功能。

我们建立一个页面,用来调节windows的屏幕亮度。

建立一个bright/pages/api/brightness.ts文件:

const nircmd = require('nircmd');
const handler = async (_req: NextApiRequest, res: NextApiResponse) => {
  const { brightness } = _req.body;
  try {
    nircmd(['setbrightness', parseInt(brightness)]);
    res.status(200).json({ ok: true })
  } catch (err) {
    res.status(500).json({ statusCode: 500, message: err.message })
  }
}
export default handler

然后启动项目:

yarn dev

这时,可以向 http://localhost:3000/api/brightness 发送post请求:

{
  brightness:10
}

这样,可以发现屏幕就暗下来了。

api有了,接下来是建立前端页面。前端页面需要一个UI库,所以先添加UI库。

yarn add @material-ui/core

接下来,看前端页面 bright/pages/index.tsx 的代码:

import Slider from '@material-ui/core/Slider'
import { useEffect, useState } from 'react';
const IndexPage = () => {
  const [value, setValue] = useState(0);
  const handleChange = (event: any, newValue: number) => {
    const val = Math.round(newValue)
    setValue(val);
    fetch("/api/brightness", {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ brightness: val }),
      method: "POST"
    })
  }
  return (
    <div>
      <Slider value={value} onChange={handleChange} />
    </div>
  )
}
export default IndexPage

这样,就可以通过滑动条来改变屏幕的亮度。

但是,它只能设置亮度,还不能获取亮度,这就导致刷新页面的时候,滑动条的位置是不正确的。

因此,我们改一下后端,增加一个获取亮度的功能,它使用wmi-client库:

yarn add wmi-client

bright/pages/api/brightness.ts

const WmiClient = require('wmi-client');
const get = async () => {
    const query = 'SELECT CurrentBrightness,InstanceName FROM WmiMonitorBrightness';
    const wmi = new WmiClient({
        host: 'localhost',
        namespace: '\\\\root\\WMI'
    });
    return new Promise((resolve, reject) => {
        wmi.query(query, (err, res) => {
            if (err) {
                reject(err);
                return;
            }
            if (res.length === 0) {
                reject(new Error('Unable to find any monitors to read brightness levels from'));
                return;
            }
            resolve(res[0].CurrentBrightness / 100);
        });
    })
}
const handler = async (_req: NextApiRequest, res: NextApiResponse) => {
  const wmi_res:number = await get();
  res.status(200).json(wmi_res*100)
}

由于api有两个方法,一个是get,一个是post,因此,把两个合并到一起,现在是bright/pages/api/brightness.ts的全貌:

const nircmd = require('nircmd');
const WmiClient = require('wmi-client');
import { NextApiRequest, NextApiResponse } from 'next'

const get = async () => {
    const query = 'SELECT CurrentBrightness,InstanceName FROM WmiMonitorBrightness';
    const wmi = new WmiClient({
        host: 'localhost',
        namespace: '\\\\root\\WMI'
    });
    return new Promise((resolve, reject) => {
        wmi.query(query, (err, res) => {
            if (err) {
                reject(err);
                return;
            }
            if (res.length === 0) {
                reject(new Error('Unable to find any monitors to read brightness levels from'));
                return;
            }
            resolve(res[0].CurrentBrightness / 100);
        });
    })
}

const handler = async (_req: NextApiRequest, res: NextApiResponse) => {
    // const {
    //     query: { id, name },
    //     method,
    // } = _req
    switch (_req.method) {
        case 'GET':
            const wmi_res:number = await get();
            res.status(200).json(wmi_res*100)
            break
        case 'POST':
            const { brightness } = _req.body;
            console.log(brightness);
            try {
                nircmd(['setbrightness', parseInt(brightness)]);
                res.status(200).json({ ok: true })
            } catch (err) {
                res.status(500).json({ statusCode: 500, message: err.message })
            }
            break
        default:
            res.status(405).end() //Method Not Allowed
            break
    }

}

export default handler

接下来对前端页面进行改造,增加一个获得亮度的功能:

import Slider from '@material-ui/core/Slider'
import { useEffect, useState } from 'react';
const IndexPage = () => {
  const [value, setValue] = useState(0);
  const handleChange = (event: any, newValue: number) => {
    const val = Math.round(newValue)
    setValue(val);
    fetch("/api/brightness", {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ brightness: val }),
      method: "POST"
    })
  }
  const getbrightness = () => {
    fetch("/api/brightness").then(res => { return res.json() }).then(val => {
      setValue(Math.round(val))
    })
  }
  useEffect(() => {
    getbrightness();
  }, [])
  return (
    <div>
      <Slider value={value} onChange={handleChange} />
    </div>
  )
}
export default IndexPage

这样,就可以愉快滴通过web控制屏幕亮度了。

最后,全部代码在 github.com/codetyphon/…