mirror of
https://github.com/miaowware/qrm2.git
synced 2025-04-11 05:58:31 -04:00
parent
be042a9641
commit
77b572eb3e
@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Maps for CQ Zones, ITU Zones, ITU Regions, and Canadian prefixes.
|
||||
- Attribution for all maps.
|
||||
- Option to append ` | ?help` to the playing status.
|
||||
- `?dbconv` command to convert voltage, power, and antenna gain values.
|
||||
### Changed
|
||||
- ARRL/RAC section maps to include all current ARRL/RAC sections.
|
||||
### Fixed
|
||||
|
201
exts/dbconv.py
Normal file
201
exts/dbconv.py
Normal file
@ -0,0 +1,201 @@
|
||||
"""
|
||||
Conversion extension for qrm
|
||||
---
|
||||
Copyright (C) 2020 Abigail Gold, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
"""
|
||||
|
||||
|
||||
import math
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
import discord.ext.commands as commands
|
||||
|
||||
import common as cmn
|
||||
from data import options as opt
|
||||
|
||||
|
||||
# not sure why but UnitConverter and Unit need to be defined before DbConvCog and convert()
|
||||
class UnitConverter(commands.Converter):
|
||||
async def convert(self, ctx: commands.Context, argument: str):
|
||||
try:
|
||||
return Unit(argument)
|
||||
except ValueError as e:
|
||||
raise commands.BadArgument(message=str(e))
|
||||
|
||||
|
||||
class Unit:
|
||||
def __init__(self, raw: str):
|
||||
self.raw: str = raw
|
||||
self.unit: str
|
||||
self.type: UnitType
|
||||
self.is_db: bool
|
||||
self.mult: int
|
||||
self._parse()
|
||||
|
||||
def _parse(self):
|
||||
s = self.raw.lower()
|
||||
if len(s) > 2 and s[:2] == "db":
|
||||
self.is_db = True
|
||||
if s[2:] in units:
|
||||
u = units[s[2:]]
|
||||
self.mult = u["mult"]
|
||||
self.unit = u["log"]
|
||||
self.type = u["type"]
|
||||
elif s in units:
|
||||
self.is_db = False
|
||||
u = units[s]
|
||||
self.mult = u["mult"]
|
||||
self.unit = u["scalar"]
|
||||
self.type = u["type"]
|
||||
else:
|
||||
raise ValueError(f"Invalid unit: {self.raw}")
|
||||
|
||||
def __str__(self):
|
||||
return self.unit
|
||||
|
||||
|
||||
class UnitType(Enum):
|
||||
voltage = 1
|
||||
power = 2
|
||||
antenna = 3
|
||||
|
||||
|
||||
class DbConvCog(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(name="dbconv", aliases=["dbc"], category=cmn.cat.ref)
|
||||
async def _db_conv(self, ctx: commands.Context,
|
||||
value: Optional[float] = None,
|
||||
unit_from: Optional[UnitConverter] = None,
|
||||
unit_to: Optional[UnitConverter] = None):
|
||||
"""
|
||||
Convert between decibels and scalar values for voltage, power, and antenna gain.
|
||||
|
||||
**Valid Units**
|
||||
*Voltage:* V, mV, µV, uV, dBV, dBmV, dBµV, dBuV
|
||||
*Power:* fW, mW, W, kW, dBf, dBm, dBW, dBk
|
||||
*Antenna Gain:* dBi, dBd, dBq
|
||||
"""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
if value is not None and unit_from is not None and unit_to is not None:
|
||||
converted = convert(value, unit_from, unit_to)
|
||||
|
||||
embed.title = f"{value:.3g} {unit_from} = {converted:.3g} {unit_to}"
|
||||
embed.colour = cmn.colours.good
|
||||
else:
|
||||
embed.title = "Decibel Quick Reference"
|
||||
embed.description = (
|
||||
"Decibels are a great way to easily represent large quantities that are common in electronics. "
|
||||
"There are a few main types that are used often in radio: voltage, power, and antenna gain. "
|
||||
"Here are some commonly-used reference levels for each type:"
|
||||
)
|
||||
v_db_info = ("**dBV** = relative to 1 V\n"
|
||||
"**dBmV** = relative to 1 mV (1e-3 V)\n"
|
||||
"**dBµV** = relative to 1 µV (1e-6 V)")
|
||||
embed.add_field(name="Voltage Decibels", value=v_db_info, inline=False)
|
||||
p_db_info = ("**dBW** = relative to 1 W\n"
|
||||
"**dBk** = relative to 1 kW (1e3 W)\n"
|
||||
"**dBm** = relative to 1 mW (1e-3 W)\n"
|
||||
"**dBf** = relative to 1 fW (1e-15 W)")
|
||||
embed.add_field(name="Power Decibels", value=p_db_info, inline=False)
|
||||
a_db_info = ("**dBi** = relative to a theoretical __i__sotropic radiator in free space "
|
||||
"(equal radiation in all directions)\n"
|
||||
"**dBd** = relative to a dipole in free space (0 dBd = 2.15 dBi)\n"
|
||||
"**dBq** = relative to a quarter-wave antenna in free space (0 dBq = -0.85 dBi)")
|
||||
embed.add_field(name="Antenna Gain Decibels", value=a_db_info, inline=False)
|
||||
embed.add_field(name="Use the bot to do the conversions",
|
||||
value=f"`{opt.display_prefix}dbconv [value] [unit_from] [unit_to]`",
|
||||
inline=False)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
bot.add_cog(DbConvCog(bot))
|
||||
|
||||
|
||||
def convert(initial: float, unit1: Unit, unit2: Unit):
|
||||
if unit1.type == unit2.type:
|
||||
# dB to dB
|
||||
if unit1.is_db and unit2.is_db:
|
||||
if unit1.mult == unit2.mult:
|
||||
return initial
|
||||
elif unit1.type == UnitType.voltage:
|
||||
return _calc_volt_db(_calc_volt(initial, unit1.mult), unit2.mult)
|
||||
elif unit1.type == UnitType.power:
|
||||
return _calc_power_db(_calc_power(initial, unit1.mult), unit2.mult)
|
||||
elif unit1.type == UnitType.antenna:
|
||||
return initial + (unit1.mult - unit2.mult)
|
||||
# V/W to V/W
|
||||
elif not unit1.is_db and not unit2.is_db:
|
||||
if unit1.mult == unit2.mult:
|
||||
return initial
|
||||
return initial * unit1.mult / unit2.mult
|
||||
# dB to V/W
|
||||
elif unit1.is_db and not unit2.is_db:
|
||||
if unit1.type == UnitType.voltage:
|
||||
return _calc_volt(initial, unit1.mult) / unit2.mult
|
||||
elif unit1.type == UnitType.power:
|
||||
return _calc_power(initial, unit1.mult) / unit2.mult
|
||||
# V/W to dB
|
||||
elif not unit1.is_db and unit2.is_db:
|
||||
if unit1.type == UnitType.voltage:
|
||||
return _calc_volt_db(initial * unit1.mult, unit2.mult)
|
||||
elif unit1.type == UnitType.power:
|
||||
return _calc_power_db(initial * unit1.mult, unit2.mult)
|
||||
raise ValueError(f"Can't convert between {unit1} and {unit2}")
|
||||
|
||||
|
||||
units = {
|
||||
# voltage
|
||||
"uv": {"mult": 1e-6, "scalar": "µV", "log": "dBµV", "type": UnitType.voltage},
|
||||
"µv": {"mult": 1e-6, "scalar": "µV", "log": "dBµV", "type": UnitType.voltage},
|
||||
"mv": {"mult": 1e-3, "scalar": "mV", "log": "dBmV", "type": UnitType.voltage},
|
||||
"v": {"mult": 1, "scalar": "V", "log": "dBV", "type": UnitType.voltage},
|
||||
# power
|
||||
"fw": {"mult": 1e-15, "scalar": "fW", "log": "dBf", "type": UnitType.power},
|
||||
"f": {"mult": 1e-15, "scalar": "fW", "log": "dBf", "type": UnitType.power},
|
||||
"mw": {"mult": 1e-3, "scalar": "mW", "log": "dBm", "type": UnitType.power},
|
||||
"m": {"mult": 1e-3, "scalar": "mW", "log": "dBm", "type": UnitType.power},
|
||||
"w": {"mult": 1, "scalar": "W", "log": "dBW", "type": UnitType.power},
|
||||
"kw": {"mult": 1e3, "scalar": "kW", "log": "dBk", "type": UnitType.power},
|
||||
"k": {"mult": 1e3, "scalar": "kW", "log": "dBk", "type": UnitType.power},
|
||||
# antenna
|
||||
"q": {"mult": -0.85, "scalar": None, "log": "dBq", "type": UnitType.antenna},
|
||||
"i": {"mult": 0, "scalar": None, "log": "dBi", "type": UnitType.antenna},
|
||||
"d": {"mult": 2.15, "scalar": None, "log": "dBd", "type": UnitType.antenna},
|
||||
}
|
||||
|
||||
|
||||
def _calc_power_db(p: float, ref: float):
|
||||
return 10 * math.log10(p / ref)
|
||||
|
||||
|
||||
def _calc_power(db: float, ref: float):
|
||||
return 10 ** (db / 10) * ref
|
||||
|
||||
|
||||
def _calc_volt_db(v: float, ref: float):
|
||||
return 20 * math.log10(v / ref)
|
||||
|
||||
|
||||
def _calc_volt(db: float, ref: float):
|
||||
return 10 ** (db / 20) * ref
|
||||
|
||||
|
||||
# testing code
|
||||
if __name__ == "__main__":
|
||||
while(True):
|
||||
try:
|
||||
ip = input("> ").split()
|
||||
initial = float(ip[0])
|
||||
unit1 = Unit(ip[1])
|
||||
unit2 = Unit(ip[2])
|
||||
conv = convert(initial, unit1, unit2)
|
||||
print(f"{initial:.2f} {unit1} = {conv:.2f} {unit2}")
|
||||
except ValueError as e:
|
||||
print(e)
|
@ -30,7 +30,7 @@ debug = False
|
||||
owners_uids = (200102491231092736,)
|
||||
|
||||
# The extensions to load when running the bot.
|
||||
exts = ["ae7q", "base", "fun", "grid", "ham", "image", "lookup", "morse", "qrz", "study", "weather"]
|
||||
exts = ["ae7q", "base", "fun", "grid", "ham", "image", "lookup", "morse", "qrz", "study", "weather", "dbconv"]
|
||||
|
||||
# Either "time", "random", or "fixed" (first item in statuses)
|
||||
status_mode = "fixed"
|
||||
|
Loading…
Reference in New Issue
Block a user