Skip to content

Commit

Permalink
Add optional -c command line parameter for overriding calibration_inf…
Browse files Browse the repository at this point in the history
…o for unsupported chip types
  • Loading branch information
chros73 committed Oct 29, 2022
1 parent 84b00f5 commit 40dcd79
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 30 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ bscpylgtvcommand 192.168.1.18 power_off
# values: ["system_info", "software_info", "power", "current_app", "muted", "volume", "apps", "inputs", "sound_output", "picture_settings"]
bscpylgtvcommand 192.168.1.18 upload_3d_lut_bt2020_from_file expert1 "test3d-2.cube" -s
bscpylgtvcommand -s "[\"software_info\"]" 192.168.1.18 upload_3d_lut_bt2020_from_file expert1 "test3d-2.cube"
# -c "{\"lut3d\": \"33pt\", \"dovi\": \"2019\"}" : set calibration_info for unsupported chip types (be careful!)
# values for "lut3d": "17pt", "33pt"
# values for "dovi": "2018", "2019"
bscpylgtvcommand -c "{\"lut3d\": \"33pt\", \"dovi\": \"2019\"}" 192.168.1.18 upload_3d_lut_bt2020_from_file expert1 "test3d-2.cube"
# -o : getting hello info (e.g. to get unique deviceUUID)
bscpylgtvcommand -o 192.168.1.18 get_hello_info true
# -k <client_key> : specifying a client key
Expand Down Expand Up @@ -188,9 +192,7 @@ More useful examples can be found in [docs/scripts](https://github.com/chros73/b
## Calibration functionality (in full version)
**WARNING:** *Messing with the calibration data COULD brick your TV in some circumstances, requiring a mainboard replacement. All of the currently implemented functions SHOULD be safe (although they have only been extensively tested for the 2018 Alpha 7/9, 2019/2021/2022 Alpha 9 models), but no guarantees.*

On supported models, upload to internal 1D/3D LUTs, resetting factory calibration data uploaded via calibration API, uploading custom tone mapping parameters (>=2019 models), using internal test pattern generator (iTPG, >=2019 models) and writing Dolby Vision config file is supported.

Supported models: LG OLED and LCD models with Alpha 7 and Alpha 9 chipsets
On LG WebOS TVs with Alpha 7 and Alpha 9 chipsets, upload to internal 1D/3D LUTs, resetting factory calibration data uploaded via calibration API, uploading custom tone mapping parameters (>=2019 models), using internal test pattern generator (iTPG, >=2019 models), writing Dolby Vision config file and other calibration commands are supported.

### Calibration commands

Expand All @@ -199,8 +201,8 @@ Here is a simplified version of the [image processing pipeline](https://displayc
Calibration commands can only be run while in calibration mode (controlled by `start_calibration` and `end_calibration`).
Some of the calibration commands aren't used (question mark behind the name of the method) depending on the model/firmware.
Most of the commands can be run in any mode, except for `set_tonemap_params` that is only for HDR10+HLG and `set_dolby_vision_config_data` that is only for Dolby Vision.
Only 3D LUT and Dolby Vision config related commands require `-s` (states) flag.
In general, `set_1d_en_*` (de-gamma, re-gamma) and `set_3by3_gamut_data_*`(3x3 color matrices) commands should only be used when using a unity/custom 3D LUT.
Only 3D LUT and Dolby Vision config related commands require `-s` (states) command line switch (or the use of `-c` (calibration_info) instead for unsuppported chip types if other calibration commands work fine, but be very careful!).
In general, `set_1d_en_*` (de-gamma, re-gamma) and `set_3by3_gamut_data_*` (3x3 color matrices) commands should only be used with unity/custom 3D LUT.

The following commands are supported:
```
Expand Down Expand Up @@ -405,6 +407,8 @@ bscpylgtvcommand 192.168.1.18 toggle_itpg false 0

## Development of `bscpylgtv`

### Adding available settings for newer models

A collection of useful commands and scripts are available under [docs/utils](https://github.com/chros73/bscpylgtv/tree/master/docs/utils) directory to add support for new firmwares in the future and make PRs easier to do.

### Adding new chip type
Expand All @@ -429,7 +433,7 @@ pytest tests
# Run all the tests in one file
pytest tests/test_webos_client_lite.py
# Run a specific test in one file
pytest tests/test_webos_client_calibration.py -k "test_set_ui_data_methods"
pytest tests/test_webos_client_calibration.py -k test_set_ui_data_methods
```


Expand Down
8 changes: 7 additions & 1 deletion bscpylgtv/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async def list_keys(path_key_file):

async def runloop(args):
client = await WebOsClient.create(args.host, ping_interval=None, get_hello_info=args.get_hello_info,
states=args.states, client_key=args.key, key_file_path=args.path_key_file)
states=args.states, calibration_info=args.calibration_info, client_key=args.key, key_file_path=args.path_key_file)
await client.connect()
print(await getattr(client, args.command)(*args.parameters))
await client.disconnect()
Expand Down Expand Up @@ -79,6 +79,12 @@ def bscpylgtvcommand():
const='["software_info"]',
help='optional setting states ("software_info" static state is required by some of the calibration commands)'
)
parser.add_argument(
"-c", "--set_calibration_info",
dest="calibration_info",
type=convert_arg,
help='optional setting calibration info (for couple of calibration commands when chip type is not supported)'
)
parser.add_argument(
"host", type=str, help="hostname or ip address of the TV to connect to"
)
Expand Down
10 changes: 8 additions & 2 deletions bscpylgtv/webos_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def __init__(
get_hello_info=False,
states=["system_info", "software_info", "power", "current_app", "muted",
"volume", "apps", "inputs", "sound_output", "picture_settings"],
calibration_info=None,
storage: StorageProto=None,
):
"""Initialize the client."""
Expand Down Expand Up @@ -92,7 +93,7 @@ def __init__(
self._system_info = None
self._software_info = None
self._hello_info = None
self._calibration_info = None
self._calibration_info = {}
self._sound_output = None
self._picture_settings = None
self.state_update_callbacks = []
Expand All @@ -104,6 +105,11 @@ def __init__(
else None
)
self.states = (set(states) if isinstance(states, list) else set())
if calibration_info and isinstance(calibration_info, dict):
if "lut3d" in calibration_info and calibration_info["lut3d"] in LUT3D_SIZES:
self._calibration_info['lut3d'] = LUT3D_SIZES[calibration_info["lut3d"]]
if "dovi" in calibration_info and calibration_info["dovi"] in DV_CONFIG_TYPES:
self._calibration_info['dovi'] = DV_CONFIG_TYPES[calibration_info["dovi"]]

@classmethod
async def create(cls, *args, **kwargs):
Expand Down Expand Up @@ -2142,7 +2148,7 @@ async def settings(payload):
# Calibration

def calibration_support_info(self):
if self._calibration_info is None:
if not self._calibration_info:
if self._software_info is None:
raise PyLGTVCmdException(f"Software info is not available, -s command line switch is required.")

Expand Down
63 changes: 42 additions & 21 deletions tests/test_webos_client_lite.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,56 @@
class TestWebOsClientLite():

data_calibration_support_info = [
( 'HE_DTV_W17H_XXXXXXXX', (None, None) ),
( 'HE_DTV_W17O_XXXXXXXX', (None, None) ),
( 'HE_DTV_W99H_XXXXXXXX', {"foo": "17pt", "dovi": "2019" }, None, 2019, 0 ),
( 'HE_DTV_W99H_XXXXXXXX', {"lut3d": "foo", "dovi": "2019" }, None, 2019, 0 ),
( 'HE_DTV_W99H_XXXXXXXX', {"lut3d": "17pt", "foo": "2019" }, 17, None, 0 ),
( 'HE_DTV_W99H_XXXXXXXX', {"lut3d": "17pt", "dovi": "foo" }, 17, None, 0 ),
( 'HE_DTV_W99H_XXXXXXXX', {"lut3d": "17pt" }, 17, None, 0 ),
( 'HE_DTV_W99H_XXXXXXXX', {"dovi": "2019" }, None, 2019, 0 ),

( 'HE_DTV_W18H_XXXXXXXX', (17, 2018) ),
( 'HE_DTV_W18O_XXXXXXXX', (33, 2018) ),
( 'HE_DTV_W99H_XXXXXXXX', {"foo": "17pt", "foo": "2019" }, None, None, 1 ),
( 'HE_DTV_W99H_XXXXXXXX', {"lut3d": "foo", "dovi": "foo" }, None, None, 1 ),
( 'HE_DTV_W99H_XXXXXXXX', {"lut3d": "17pt", "dovi": "2019" }, 17, 2019, 1 ),
( 'HE_DTV_W99O_XXXXXXXX', {"lut3d": "33pt", "dovi": "2019" }, 33, 2019, 1 ),
( None, {"lut3d": "17pt", "dovi": "2019" }, 17, 2019, 1 ),
( None, {"lut3d": "33pt", "dovi": "2019" }, 33, 2019, 1 ),

( 'HE_DTV_W19H_XXXXXXXX', (17, 2019) ),
( 'HE_DTV_W19O_XXXXXXXX', (33, 2019) ),
( 'HE_DTV_W17H_XXXXXXXX', None, None, None, 1 ),
( 'HE_DTV_W17O_XXXXXXXX', None, None, None, 1 ),

( 'HE_DTV_W20H_XXXXXXXX', (17, 2019) ),
( 'HE_DTV_W20O_XXXXXXXX', (33, 2019) ),
( 'HE_DTV_W18H_XXXXXXXX', None, 17, 2018, 1 ),
( 'HE_DTV_W18O_XXXXXXXX', None, 33, 2018, 1 ),

( 'HE_DTV_W21H_XXXXXXXX', (17, 2019) ),
( 'HE_DTV_W21O_XXXXXXXX', (33, 2019) ),
( 'HE_DTV_W19H_XXXXXXXX', None, 17, 2019, 1 ),
( 'HE_DTV_W19O_XXXXXXXX', None, 33, 2019, 1 ),

( 'HE_DTV_W22H_XXXXXXXX', (17, 2019) ),
( 'HE_DTV_W22O_XXXXXXXX', (33, 2019) ),
( 'HE_DTV_W20H_XXXXXXXX', None, 17, 2019, 1 ),
( 'HE_DTV_W20O_XXXXXXXX', None, 33, 2019, 1 ),

( 'HE_DTV_W21H_XXXXXXXX', None, 17, 2019, 1 ),
( 'HE_DTV_W21O_XXXXXXXX', None, 33, 2019, 1 ),

( 'HE_DTV_W22H_XXXXXXXX', None, 17, 2019, 1 ),
( 'HE_DTV_W22O_XXXXXXXX', None, 33, 2019, 1 ),
]

@pytest.mark.parametrize("model,expected", data_calibration_support_info)
async def test_calibration_support_info(self, model, expected):
client = await WebOsClient.create("x", states=["software_info"], client_key="x")
@pytest.mark.parametrize("model,calInfo,lut3d,dovi,expected", data_calibration_support_info)
async def test_calibration_support_info(self, model, calInfo, lut3d, dovi, expected):
client = await WebOsClient.create("x", states=["software_info"], calibration_info=calInfo, client_key="x")
client._software_info = {"model_name" : model}
client.calibration_support_info()

expected = {
"lut3d": expected[0],
"dovi": expected[1],
}

assert expected == client._calibration_info
if expected > 0:
cal_info = {
"lut3d": lut3d,
"dovi": dovi,
}
else:
cal_info = {}
if lut3d:
cal_info["lut3d"] = lut3d
if dovi:
cal_info["dovi"] = dovi

assert cal_info == client._calibration_info

0 comments on commit 40dcd79

Please sign in to comment.