Good enough. That is first time you explained you are going to use one or the other but not both together, so no, you didn't explain it, so how could anyone, including me, understand what you were trying to do?
Try using AI to build your driver. This is what I got with "Create a virtual driver for hubitat, that will take an input of a date and a sun altitude value in a command, and output the time of day the sun will be at that altitude, set in an attribute" Then repeat to get a driver for Azimuth.
metadata {
definition(name: "Sun Altitude Calculator", namespace: "yourNamespace", author: "Your Name") {
capability "Initialize"
command "calculateSunAltitudeTime", ["date", "number"]
attribute "sunAltitudeTime", "string"
attribute "lastCalculation", "string"
attribute "targetAltitude", "number"
}
preferences {
input name: "latitude", type: "number", title: "Latitude", description: "Your location's latitude", required: true, defaultValue: 0
input name: "longitude", type: "number", title: "Longitude", description: "Your location's longitude", required: true, defaultValue: 0
input name: "timeZone", type: "text", title: "Time Zone", description: "Your time zone (e.g., America/New_York)", required: true
input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
}
}
def installed() {
log.info "Sun Altitude Calculator installed"
initialize()
}
def updated() {
log.info "Sun Altitude Calculator updated"
initialize()
}
def initialize() {
log.info "Sun Altitude Calculator initialized"
if (logEnable) runIn(1800, logsOff)
}
def logsOff() {
log.warn "Debug logging disabled"
device.updateSetting("logEnable", [value:"false", type:"bool"])
}
def calculateSunAltitudeTime(date, altitude) {
if (logEnable) log.debug "Calculating sun altitude time for date: ${date}, altitude: ${altitude}°"
try {
// Validate inputs
if (!latitude || !longitude) {
log.error "Latitude and longitude must be set in preferences"
return
}
def targetDate = Date.parse("yyyy-MM-dd", date)
def targetAlt = altitude.toDouble()
// Set attributes for tracking
sendEvent(name: "targetAltitude", value: targetAlt)
sendEvent(name: "lastCalculation", value: new Date().format("yyyy-MM-dd HH:mm:ss", location.timeZone))
// Calculate sunrise/sunset times for reference
def location = new Date().location
def sunTimes = getSunriseAndSunset(date: targetDate, location: location)
// This is where the actual calculation would happen
// Note: This is a simplified approximation - a real implementation would need
// proper astronomical calculations or a library like JSUNTIME
// For demonstration, we'll use a simple approximation:
// Assume solar noon is halfway between sunrise and sunset
// And altitude changes linearly (which isn't accurate, but works for demo)
def sunrise = sunTimes.sunrise
def sunset = sunTimes.sunset
def solarNoon = new Date((sunrise.time + sunset.time) / 2)
// Max altitude at solar noon (simplified)
def maxAltitude = 90 - Math.abs(latitude - targetDate.declination())
if (targetAlt > maxAltitude) {
log.warn "Requested altitude ${targetAlt}° is higher than maximum sun altitude ${maxAltitude}° for this date"
sendEvent(name: "sunAltitudeTime", value: "Never (too high)")
return
}
// Calculate approximate times (morning and afternoon)
// This is a very rough approximation - real implementation would need proper math
def fraction = targetAlt / maxAltitude
def timeOffset = (solarNoon.time - sunrise.time) * fraction
def morningTime = new Date(sunrise.time + timeOffset)
def afternoonTime = new Date(solarNoon.time + (solarNoon.time - morningTime.time))
def result = "${morningTime.format("HH:mm", location.timeZone)} or ${afternoonTime.format("HH:mm", location.timeZone)}"
sendEvent(name: "sunAltitudeTime", value: result)
if (logEnable) log.debug "Calculated sun altitude time: ${result}"
} catch (Exception e) {
log.error "Error calculating sun altitude time: ${e}"
sendEvent(name: "sunAltitudeTime", value: "Error")
}
}
// Helper method to get sunrise/sunset times
private getSunriseAndSunset(Map params) {
def date = params.date ?: new Date()
def location = params.location ?: new Date().location
def calendar = Calendar.getInstance(location.timeZone)
calendar.time = date
def sunriseSunset = location.sunriseSunset(calendar)
return [
sunrise: sunriseSunset.sunrise,
sunset: sunriseSunset.sunset
]
}